How does XPath deal with XML namespaces?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







20















How does XPath deal with XML namespaces?



If I use



/IntuitResponse/QueryResponse/Bill/Id


to parse the XML document below I get 0 nodes back.



<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IntuitResponse xmlns="http://schema.intuit.com/finance/v3"
time="2016-10-14T10:48:39.109-07:00">
<QueryResponse startPosition="1" maxResults="79" totalCount="79">
<Bill domain="QBO" sparse="false">
<Id>=1</Id>
</Bill>
</QueryResponse>
</IntuitResponse>


However, I'm not specifying the namespace in the XPath (i.e. http://schema.intuit.com/finance/v3 is not a prefix of each token of the path). How can XPath know which Id I want if I don't tell it explicitly? I suppose in this case (since there is only one namespace) XPath could get away with ignoring the xmlns entirely. But if there are multiple namespaces, things could get ugly.










share|improve this question

























  • Your XPath should not return any node : INFO - XPath returned 0 items (compiled in 0ms, evaluated in 1ms). How did you execute the XPath?

    – har07
    Nov 25 '16 at 0:57











  • @har07 I did it in Java using import javax.xml.xpath.XPath. I agree it doesn't work using an online tester. That was one of the perplexing things.

    – Adam
    Nov 25 '16 at 1:16













  • Excellent question! XPath itself provides no way to specify a default namespace or the binding of a namespace prefix to a namespace. Fortunately, however, hosting languages and libraries do. See my answer below for details...

    – kjhughes
    Nov 25 '16 at 1:17













  • Not quite sure why a question should be upvoted so highly when it has been asked and answered 1000 times before....

    – Michael Kay
    Nov 25 '16 at 8:52






  • 1





    I for one was impressed with this question because, unlike most previous askers, Adam not only included a Minimal, Complete, and Verifiable example, he sensed and conveyed the need for XPath to deal with XML namespaces somehow. Most such questions merely post an XPath, maybe some XML (and if we're lucky it's not an image or a link to a humongous off-site resource), and state that it "doesn't work." Adam sensed it had to do with namespaces, nailed the title, and wrote what I considered to be a question worthy of a canonical answer.

    – kjhughes
    Nov 25 '16 at 15:59


















20















How does XPath deal with XML namespaces?



If I use



/IntuitResponse/QueryResponse/Bill/Id


to parse the XML document below I get 0 nodes back.



<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IntuitResponse xmlns="http://schema.intuit.com/finance/v3"
time="2016-10-14T10:48:39.109-07:00">
<QueryResponse startPosition="1" maxResults="79" totalCount="79">
<Bill domain="QBO" sparse="false">
<Id>=1</Id>
</Bill>
</QueryResponse>
</IntuitResponse>


However, I'm not specifying the namespace in the XPath (i.e. http://schema.intuit.com/finance/v3 is not a prefix of each token of the path). How can XPath know which Id I want if I don't tell it explicitly? I suppose in this case (since there is only one namespace) XPath could get away with ignoring the xmlns entirely. But if there are multiple namespaces, things could get ugly.










share|improve this question

























  • Your XPath should not return any node : INFO - XPath returned 0 items (compiled in 0ms, evaluated in 1ms). How did you execute the XPath?

    – har07
    Nov 25 '16 at 0:57











  • @har07 I did it in Java using import javax.xml.xpath.XPath. I agree it doesn't work using an online tester. That was one of the perplexing things.

    – Adam
    Nov 25 '16 at 1:16













  • Excellent question! XPath itself provides no way to specify a default namespace or the binding of a namespace prefix to a namespace. Fortunately, however, hosting languages and libraries do. See my answer below for details...

    – kjhughes
    Nov 25 '16 at 1:17













  • Not quite sure why a question should be upvoted so highly when it has been asked and answered 1000 times before....

    – Michael Kay
    Nov 25 '16 at 8:52






  • 1





    I for one was impressed with this question because, unlike most previous askers, Adam not only included a Minimal, Complete, and Verifiable example, he sensed and conveyed the need for XPath to deal with XML namespaces somehow. Most such questions merely post an XPath, maybe some XML (and if we're lucky it's not an image or a link to a humongous off-site resource), and state that it "doesn't work." Adam sensed it had to do with namespaces, nailed the title, and wrote what I considered to be a question worthy of a canonical answer.

    – kjhughes
    Nov 25 '16 at 15:59














20












20








20


5






How does XPath deal with XML namespaces?



If I use



/IntuitResponse/QueryResponse/Bill/Id


to parse the XML document below I get 0 nodes back.



<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IntuitResponse xmlns="http://schema.intuit.com/finance/v3"
time="2016-10-14T10:48:39.109-07:00">
<QueryResponse startPosition="1" maxResults="79" totalCount="79">
<Bill domain="QBO" sparse="false">
<Id>=1</Id>
</Bill>
</QueryResponse>
</IntuitResponse>


However, I'm not specifying the namespace in the XPath (i.e. http://schema.intuit.com/finance/v3 is not a prefix of each token of the path). How can XPath know which Id I want if I don't tell it explicitly? I suppose in this case (since there is only one namespace) XPath could get away with ignoring the xmlns entirely. But if there are multiple namespaces, things could get ugly.










share|improve this question
















How does XPath deal with XML namespaces?



If I use



/IntuitResponse/QueryResponse/Bill/Id


to parse the XML document below I get 0 nodes back.



<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IntuitResponse xmlns="http://schema.intuit.com/finance/v3"
time="2016-10-14T10:48:39.109-07:00">
<QueryResponse startPosition="1" maxResults="79" totalCount="79">
<Bill domain="QBO" sparse="false">
<Id>=1</Id>
</Bill>
</QueryResponse>
</IntuitResponse>


However, I'm not specifying the namespace in the XPath (i.e. http://schema.intuit.com/finance/v3 is not a prefix of each token of the path). How can XPath know which Id I want if I don't tell it explicitly? I suppose in this case (since there is only one namespace) XPath could get away with ignoring the xmlns entirely. But if there are multiple namespaces, things could get ugly.







xml xpath xml-namespaces






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 25 '16 at 1:18









kjhughes

67.6k1394134




67.6k1394134










asked Nov 25 '16 at 0:43









AdamAdam

2,28562952




2,28562952













  • Your XPath should not return any node : INFO - XPath returned 0 items (compiled in 0ms, evaluated in 1ms). How did you execute the XPath?

    – har07
    Nov 25 '16 at 0:57











  • @har07 I did it in Java using import javax.xml.xpath.XPath. I agree it doesn't work using an online tester. That was one of the perplexing things.

    – Adam
    Nov 25 '16 at 1:16













  • Excellent question! XPath itself provides no way to specify a default namespace or the binding of a namespace prefix to a namespace. Fortunately, however, hosting languages and libraries do. See my answer below for details...

    – kjhughes
    Nov 25 '16 at 1:17













  • Not quite sure why a question should be upvoted so highly when it has been asked and answered 1000 times before....

    – Michael Kay
    Nov 25 '16 at 8:52






  • 1





    I for one was impressed with this question because, unlike most previous askers, Adam not only included a Minimal, Complete, and Verifiable example, he sensed and conveyed the need for XPath to deal with XML namespaces somehow. Most such questions merely post an XPath, maybe some XML (and if we're lucky it's not an image or a link to a humongous off-site resource), and state that it "doesn't work." Adam sensed it had to do with namespaces, nailed the title, and wrote what I considered to be a question worthy of a canonical answer.

    – kjhughes
    Nov 25 '16 at 15:59



















  • Your XPath should not return any node : INFO - XPath returned 0 items (compiled in 0ms, evaluated in 1ms). How did you execute the XPath?

    – har07
    Nov 25 '16 at 0:57











  • @har07 I did it in Java using import javax.xml.xpath.XPath. I agree it doesn't work using an online tester. That was one of the perplexing things.

    – Adam
    Nov 25 '16 at 1:16













  • Excellent question! XPath itself provides no way to specify a default namespace or the binding of a namespace prefix to a namespace. Fortunately, however, hosting languages and libraries do. See my answer below for details...

    – kjhughes
    Nov 25 '16 at 1:17













  • Not quite sure why a question should be upvoted so highly when it has been asked and answered 1000 times before....

    – Michael Kay
    Nov 25 '16 at 8:52






  • 1





    I for one was impressed with this question because, unlike most previous askers, Adam not only included a Minimal, Complete, and Verifiable example, he sensed and conveyed the need for XPath to deal with XML namespaces somehow. Most such questions merely post an XPath, maybe some XML (and if we're lucky it's not an image or a link to a humongous off-site resource), and state that it "doesn't work." Adam sensed it had to do with namespaces, nailed the title, and wrote what I considered to be a question worthy of a canonical answer.

    – kjhughes
    Nov 25 '16 at 15:59

















Your XPath should not return any node : INFO - XPath returned 0 items (compiled in 0ms, evaluated in 1ms). How did you execute the XPath?

– har07
Nov 25 '16 at 0:57





Your XPath should not return any node : INFO - XPath returned 0 items (compiled in 0ms, evaluated in 1ms). How did you execute the XPath?

– har07
Nov 25 '16 at 0:57













@har07 I did it in Java using import javax.xml.xpath.XPath. I agree it doesn't work using an online tester. That was one of the perplexing things.

– Adam
Nov 25 '16 at 1:16







@har07 I did it in Java using import javax.xml.xpath.XPath. I agree it doesn't work using an online tester. That was one of the perplexing things.

– Adam
Nov 25 '16 at 1:16















Excellent question! XPath itself provides no way to specify a default namespace or the binding of a namespace prefix to a namespace. Fortunately, however, hosting languages and libraries do. See my answer below for details...

– kjhughes
Nov 25 '16 at 1:17







Excellent question! XPath itself provides no way to specify a default namespace or the binding of a namespace prefix to a namespace. Fortunately, however, hosting languages and libraries do. See my answer below for details...

– kjhughes
Nov 25 '16 at 1:17















Not quite sure why a question should be upvoted so highly when it has been asked and answered 1000 times before....

– Michael Kay
Nov 25 '16 at 8:52





Not quite sure why a question should be upvoted so highly when it has been asked and answered 1000 times before....

– Michael Kay
Nov 25 '16 at 8:52




1




1





I for one was impressed with this question because, unlike most previous askers, Adam not only included a Minimal, Complete, and Verifiable example, he sensed and conveyed the need for XPath to deal with XML namespaces somehow. Most such questions merely post an XPath, maybe some XML (and if we're lucky it's not an image or a link to a humongous off-site resource), and state that it "doesn't work." Adam sensed it had to do with namespaces, nailed the title, and wrote what I considered to be a question worthy of a canonical answer.

– kjhughes
Nov 25 '16 at 15:59





I for one was impressed with this question because, unlike most previous askers, Adam not only included a Minimal, Complete, and Verifiable example, he sensed and conveyed the need for XPath to deal with XML namespaces somehow. Most such questions merely post an XPath, maybe some XML (and if we're lucky it's not an image or a link to a humongous off-site resource), and state that it "doesn't work." Adam sensed it had to do with namespaces, nailed the title, and wrote what I considered to be a question worthy of a canonical answer.

– kjhughes
Nov 25 '16 at 15:59












1 Answer
1






active

oldest

votes


















29














Defining namespaces in XPath (recommended)



XPath itself doesn't have a way to bind a namespace prefix with a namespace. Such facilities are provided by the hosting library.



It is recommended that you use those facilities and define namespace prefixes that can then be used to qualify XML element and attribute names as necessary.





Here are some of the various mechanisms which XPath hosts provide for specifying namespace prefix bindings to namespace URIs:



XSLT:



<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:i="http://schema.intuit.com/finance/v3">
...


Perl (LibXML):



my $xc = XML::LibXML::XPathContext->new($doc);
$xc->registerNs('i', 'http://schema.intuit.com/finance/v3');
my @nodes = $xc->findnodes('/i:IntuitResponse/i:QueryResponse');


Python (lxml):



from lxml import etree
f = StringIO('<IntuitResponse>...</IntuitResponse>')
doc = etree.parse(f)
r = doc.xpath('/i:IntuitResponse/i:QueryResponse',
namespaces={'i':'http://schema.intuit.com/finance/v3'})


Python (ElementTree):



namespaces = {'i': 'http://schema.intuit.com/finance/v3'}
root.findall('/i:IntuitResponse/i:QueryResponse', namespaces)


Java (SAX):



NamespaceSupport support = new NamespaceSupport();
support.pushContext();
support.declarePrefix("i", "http://schema.intuit.com/finance/v3");


Java (XPath):



xpath.setNamespaceContext(new NamespaceContext() {
public String getNamespaceURI(String prefix) {
switch (prefix) {
case "i": return "http://schema.intuit.com/finance/v3";
// ...
}
});



  • Remember to call
    DocumentBuilderFactory.setNamespaceAware(true).

  • See also:
    Java XPath: Queries with default namespace xmlns


xmlstarlet:



-N i="http://schema.intuit.com/finance/v3"


JavaScript:



See Implementing a User Defined Namespace Resolver:



function nsResolver(prefix) {
var ns = {
'i' : 'http://schema.intuit.com/finance/v3'
};
return ns[prefix] || null;
}
document.evaluate( '/i:IntuitResponse/i:QueryResponse',
document, nsResolver, XPathResult.ANY_TYPE,
null );


PhP:



Adapted from @Tomalak's answer using DOMDocument:



$result = new DOMDocument();
$result->loadXML($xml);

$xpath = new DOMXpath($result);
$xpath->registerNamespace("i", "http://schema.intuit.com/finance/v3");

$result = $xpath->query("/i:IntuitResponse/i:QueryResponse");


See also @IMSoP's canonical Q/A on PHP SimpleXML namespaces.



C#:



XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3");
XmlNodeList nodes = el.SelectNodes(@"/i:IntuitResponse/i:QueryResponse", nsmgr);


VBA:



xmlNS = "xmlns:i='http://schema.intuit.com/finance/v3'"
doc.setProperty "SelectionNamespaces", xmlNS
Set queryResponseElement =doc.SelectSingleNode("/i:IntuitResponse/i:QueryResponse")


VB.NET:



xmlDoc = New XmlDocument()
xmlDoc.Load("file.xml")
nsmgr = New XmlNamespaceManager(New XmlNameTable())
nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3");
nodes = xmlDoc.DocumentElement.SelectNodes("/i:IntuitResponse/i:QueryResponse",
nsmgr)


Ruby (Nokogiri):



puts doc.xpath('/i:IntuitResponse/i:QueryResponse',
'i' => "http://schema.intuit.com/finance/v3")


Note that Nokogiri supports removal of namespaces,



doc.remove_namespaces!


but see the below warnings discouraging the defeating of XML namespaces.





Once you've declared a namespace prefix, your XPath can be written to use it:



/i:IntuitResponse/i:QueryResponse




Defeating namespaces in XPath (not recommended)



An alternative is to write predicates that test against local-name():



/*[local-name()='IntuitResponse']/*[local-name()='QueryResponse']/@startPosition


Or, in XPath 2.0:



/*:IntuitResponse/*:QueryResponse/@startPosition


Skirting namespaces in this manner works but is not recommended because it




  • Under-specifies the full element/attribute name.


  • Fails to differentiate between element/attribute names in different
    namespaces (the very purpose of namespaces). Note that this concern could be addressed by adding an additional predicate to check the namespace URI explicitly1:



    /*[    namespace-uri()='http://schema.intuit.com/finance/v3' 
    and local-name()='IntuitResponse']
    /*[ namespace-uri()='http://schema.intuit.com/finance/v3'
    and local-name()='QueryResponse']
    /@startPosition


    1Thanks to Daniel Haley for the namespace-uri() note.



  • Is excessively verbose.







share|improve this answer


























  • Thank you for such a complete answer. One thing I still don't understand though is how when I use a library like Javax or Pugi XML to parse the XML above with the path I specified, I actually do get results (i.e. a node list) back. Do some of these libraries have an ability to somehow infer simple namespaces?

    – Adam
    Nov 25 '16 at 17:42








  • 1





    pugi: nonconformance declaration in docs + odd behavior observation = turn and run / life's too short. Javax: Don't forget to call setNamespaceAware(true) on the DocumentBuilderFactory.

    – kjhughes
    Nov 25 '16 at 19:56








  • 2





    Turns out pugixml doesn't support xml namespaces at all (stackoverflow.com/questions/1042855/…). Turning and running.

    – Adam
    Nov 25 '16 at 21:10








  • 1





    @DougGlancy: Sorry, VBA was one of the few examples I'd not yet provided. Remedied by adding now. Note that unqualified attribute names are not automatically placed in the default namespace specified on ancestor elements. I've reopened your other question since other than this detail, you'd already accounted for namespaces properly. Let me know here if I can help in general with XPath and namespaces or over on your question if particular to that issue. Thanks.

    – kjhughes
    Nov 20 '17 at 4:09








  • 1





    Thanks, very helpful.

    – Doug Glancy
    Nov 20 '17 at 4:18












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f40796231%2fhow-does-xpath-deal-with-xml-namespaces%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









29














Defining namespaces in XPath (recommended)



XPath itself doesn't have a way to bind a namespace prefix with a namespace. Such facilities are provided by the hosting library.



It is recommended that you use those facilities and define namespace prefixes that can then be used to qualify XML element and attribute names as necessary.





Here are some of the various mechanisms which XPath hosts provide for specifying namespace prefix bindings to namespace URIs:



XSLT:



<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:i="http://schema.intuit.com/finance/v3">
...


Perl (LibXML):



my $xc = XML::LibXML::XPathContext->new($doc);
$xc->registerNs('i', 'http://schema.intuit.com/finance/v3');
my @nodes = $xc->findnodes('/i:IntuitResponse/i:QueryResponse');


Python (lxml):



from lxml import etree
f = StringIO('<IntuitResponse>...</IntuitResponse>')
doc = etree.parse(f)
r = doc.xpath('/i:IntuitResponse/i:QueryResponse',
namespaces={'i':'http://schema.intuit.com/finance/v3'})


Python (ElementTree):



namespaces = {'i': 'http://schema.intuit.com/finance/v3'}
root.findall('/i:IntuitResponse/i:QueryResponse', namespaces)


Java (SAX):



NamespaceSupport support = new NamespaceSupport();
support.pushContext();
support.declarePrefix("i", "http://schema.intuit.com/finance/v3");


Java (XPath):



xpath.setNamespaceContext(new NamespaceContext() {
public String getNamespaceURI(String prefix) {
switch (prefix) {
case "i": return "http://schema.intuit.com/finance/v3";
// ...
}
});



  • Remember to call
    DocumentBuilderFactory.setNamespaceAware(true).

  • See also:
    Java XPath: Queries with default namespace xmlns


xmlstarlet:



-N i="http://schema.intuit.com/finance/v3"


JavaScript:



See Implementing a User Defined Namespace Resolver:



function nsResolver(prefix) {
var ns = {
'i' : 'http://schema.intuit.com/finance/v3'
};
return ns[prefix] || null;
}
document.evaluate( '/i:IntuitResponse/i:QueryResponse',
document, nsResolver, XPathResult.ANY_TYPE,
null );


PhP:



Adapted from @Tomalak's answer using DOMDocument:



$result = new DOMDocument();
$result->loadXML($xml);

$xpath = new DOMXpath($result);
$xpath->registerNamespace("i", "http://schema.intuit.com/finance/v3");

$result = $xpath->query("/i:IntuitResponse/i:QueryResponse");


See also @IMSoP's canonical Q/A on PHP SimpleXML namespaces.



C#:



XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3");
XmlNodeList nodes = el.SelectNodes(@"/i:IntuitResponse/i:QueryResponse", nsmgr);


VBA:



xmlNS = "xmlns:i='http://schema.intuit.com/finance/v3'"
doc.setProperty "SelectionNamespaces", xmlNS
Set queryResponseElement =doc.SelectSingleNode("/i:IntuitResponse/i:QueryResponse")


VB.NET:



xmlDoc = New XmlDocument()
xmlDoc.Load("file.xml")
nsmgr = New XmlNamespaceManager(New XmlNameTable())
nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3");
nodes = xmlDoc.DocumentElement.SelectNodes("/i:IntuitResponse/i:QueryResponse",
nsmgr)


Ruby (Nokogiri):



puts doc.xpath('/i:IntuitResponse/i:QueryResponse',
'i' => "http://schema.intuit.com/finance/v3")


Note that Nokogiri supports removal of namespaces,



doc.remove_namespaces!


but see the below warnings discouraging the defeating of XML namespaces.





Once you've declared a namespace prefix, your XPath can be written to use it:



/i:IntuitResponse/i:QueryResponse




Defeating namespaces in XPath (not recommended)



An alternative is to write predicates that test against local-name():



/*[local-name()='IntuitResponse']/*[local-name()='QueryResponse']/@startPosition


Or, in XPath 2.0:



/*:IntuitResponse/*:QueryResponse/@startPosition


Skirting namespaces in this manner works but is not recommended because it




  • Under-specifies the full element/attribute name.


  • Fails to differentiate between element/attribute names in different
    namespaces (the very purpose of namespaces). Note that this concern could be addressed by adding an additional predicate to check the namespace URI explicitly1:



    /*[    namespace-uri()='http://schema.intuit.com/finance/v3' 
    and local-name()='IntuitResponse']
    /*[ namespace-uri()='http://schema.intuit.com/finance/v3'
    and local-name()='QueryResponse']
    /@startPosition


    1Thanks to Daniel Haley for the namespace-uri() note.



  • Is excessively verbose.







share|improve this answer


























  • Thank you for such a complete answer. One thing I still don't understand though is how when I use a library like Javax or Pugi XML to parse the XML above with the path I specified, I actually do get results (i.e. a node list) back. Do some of these libraries have an ability to somehow infer simple namespaces?

    – Adam
    Nov 25 '16 at 17:42








  • 1





    pugi: nonconformance declaration in docs + odd behavior observation = turn and run / life's too short. Javax: Don't forget to call setNamespaceAware(true) on the DocumentBuilderFactory.

    – kjhughes
    Nov 25 '16 at 19:56








  • 2





    Turns out pugixml doesn't support xml namespaces at all (stackoverflow.com/questions/1042855/…). Turning and running.

    – Adam
    Nov 25 '16 at 21:10








  • 1





    @DougGlancy: Sorry, VBA was one of the few examples I'd not yet provided. Remedied by adding now. Note that unqualified attribute names are not automatically placed in the default namespace specified on ancestor elements. I've reopened your other question since other than this detail, you'd already accounted for namespaces properly. Let me know here if I can help in general with XPath and namespaces or over on your question if particular to that issue. Thanks.

    – kjhughes
    Nov 20 '17 at 4:09








  • 1





    Thanks, very helpful.

    – Doug Glancy
    Nov 20 '17 at 4:18
















29














Defining namespaces in XPath (recommended)



XPath itself doesn't have a way to bind a namespace prefix with a namespace. Such facilities are provided by the hosting library.



It is recommended that you use those facilities and define namespace prefixes that can then be used to qualify XML element and attribute names as necessary.





Here are some of the various mechanisms which XPath hosts provide for specifying namespace prefix bindings to namespace URIs:



XSLT:



<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:i="http://schema.intuit.com/finance/v3">
...


Perl (LibXML):



my $xc = XML::LibXML::XPathContext->new($doc);
$xc->registerNs('i', 'http://schema.intuit.com/finance/v3');
my @nodes = $xc->findnodes('/i:IntuitResponse/i:QueryResponse');


Python (lxml):



from lxml import etree
f = StringIO('<IntuitResponse>...</IntuitResponse>')
doc = etree.parse(f)
r = doc.xpath('/i:IntuitResponse/i:QueryResponse',
namespaces={'i':'http://schema.intuit.com/finance/v3'})


Python (ElementTree):



namespaces = {'i': 'http://schema.intuit.com/finance/v3'}
root.findall('/i:IntuitResponse/i:QueryResponse', namespaces)


Java (SAX):



NamespaceSupport support = new NamespaceSupport();
support.pushContext();
support.declarePrefix("i", "http://schema.intuit.com/finance/v3");


Java (XPath):



xpath.setNamespaceContext(new NamespaceContext() {
public String getNamespaceURI(String prefix) {
switch (prefix) {
case "i": return "http://schema.intuit.com/finance/v3";
// ...
}
});



  • Remember to call
    DocumentBuilderFactory.setNamespaceAware(true).

  • See also:
    Java XPath: Queries with default namespace xmlns


xmlstarlet:



-N i="http://schema.intuit.com/finance/v3"


JavaScript:



See Implementing a User Defined Namespace Resolver:



function nsResolver(prefix) {
var ns = {
'i' : 'http://schema.intuit.com/finance/v3'
};
return ns[prefix] || null;
}
document.evaluate( '/i:IntuitResponse/i:QueryResponse',
document, nsResolver, XPathResult.ANY_TYPE,
null );


PhP:



Adapted from @Tomalak's answer using DOMDocument:



$result = new DOMDocument();
$result->loadXML($xml);

$xpath = new DOMXpath($result);
$xpath->registerNamespace("i", "http://schema.intuit.com/finance/v3");

$result = $xpath->query("/i:IntuitResponse/i:QueryResponse");


See also @IMSoP's canonical Q/A on PHP SimpleXML namespaces.



C#:



XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3");
XmlNodeList nodes = el.SelectNodes(@"/i:IntuitResponse/i:QueryResponse", nsmgr);


VBA:



xmlNS = "xmlns:i='http://schema.intuit.com/finance/v3'"
doc.setProperty "SelectionNamespaces", xmlNS
Set queryResponseElement =doc.SelectSingleNode("/i:IntuitResponse/i:QueryResponse")


VB.NET:



xmlDoc = New XmlDocument()
xmlDoc.Load("file.xml")
nsmgr = New XmlNamespaceManager(New XmlNameTable())
nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3");
nodes = xmlDoc.DocumentElement.SelectNodes("/i:IntuitResponse/i:QueryResponse",
nsmgr)


Ruby (Nokogiri):



puts doc.xpath('/i:IntuitResponse/i:QueryResponse',
'i' => "http://schema.intuit.com/finance/v3")


Note that Nokogiri supports removal of namespaces,



doc.remove_namespaces!


but see the below warnings discouraging the defeating of XML namespaces.





Once you've declared a namespace prefix, your XPath can be written to use it:



/i:IntuitResponse/i:QueryResponse




Defeating namespaces in XPath (not recommended)



An alternative is to write predicates that test against local-name():



/*[local-name()='IntuitResponse']/*[local-name()='QueryResponse']/@startPosition


Or, in XPath 2.0:



/*:IntuitResponse/*:QueryResponse/@startPosition


Skirting namespaces in this manner works but is not recommended because it




  • Under-specifies the full element/attribute name.


  • Fails to differentiate between element/attribute names in different
    namespaces (the very purpose of namespaces). Note that this concern could be addressed by adding an additional predicate to check the namespace URI explicitly1:



    /*[    namespace-uri()='http://schema.intuit.com/finance/v3' 
    and local-name()='IntuitResponse']
    /*[ namespace-uri()='http://schema.intuit.com/finance/v3'
    and local-name()='QueryResponse']
    /@startPosition


    1Thanks to Daniel Haley for the namespace-uri() note.



  • Is excessively verbose.







share|improve this answer


























  • Thank you for such a complete answer. One thing I still don't understand though is how when I use a library like Javax or Pugi XML to parse the XML above with the path I specified, I actually do get results (i.e. a node list) back. Do some of these libraries have an ability to somehow infer simple namespaces?

    – Adam
    Nov 25 '16 at 17:42








  • 1





    pugi: nonconformance declaration in docs + odd behavior observation = turn and run / life's too short. Javax: Don't forget to call setNamespaceAware(true) on the DocumentBuilderFactory.

    – kjhughes
    Nov 25 '16 at 19:56








  • 2





    Turns out pugixml doesn't support xml namespaces at all (stackoverflow.com/questions/1042855/…). Turning and running.

    – Adam
    Nov 25 '16 at 21:10








  • 1





    @DougGlancy: Sorry, VBA was one of the few examples I'd not yet provided. Remedied by adding now. Note that unqualified attribute names are not automatically placed in the default namespace specified on ancestor elements. I've reopened your other question since other than this detail, you'd already accounted for namespaces properly. Let me know here if I can help in general with XPath and namespaces or over on your question if particular to that issue. Thanks.

    – kjhughes
    Nov 20 '17 at 4:09








  • 1





    Thanks, very helpful.

    – Doug Glancy
    Nov 20 '17 at 4:18














29












29








29







Defining namespaces in XPath (recommended)



XPath itself doesn't have a way to bind a namespace prefix with a namespace. Such facilities are provided by the hosting library.



It is recommended that you use those facilities and define namespace prefixes that can then be used to qualify XML element and attribute names as necessary.





Here are some of the various mechanisms which XPath hosts provide for specifying namespace prefix bindings to namespace URIs:



XSLT:



<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:i="http://schema.intuit.com/finance/v3">
...


Perl (LibXML):



my $xc = XML::LibXML::XPathContext->new($doc);
$xc->registerNs('i', 'http://schema.intuit.com/finance/v3');
my @nodes = $xc->findnodes('/i:IntuitResponse/i:QueryResponse');


Python (lxml):



from lxml import etree
f = StringIO('<IntuitResponse>...</IntuitResponse>')
doc = etree.parse(f)
r = doc.xpath('/i:IntuitResponse/i:QueryResponse',
namespaces={'i':'http://schema.intuit.com/finance/v3'})


Python (ElementTree):



namespaces = {'i': 'http://schema.intuit.com/finance/v3'}
root.findall('/i:IntuitResponse/i:QueryResponse', namespaces)


Java (SAX):



NamespaceSupport support = new NamespaceSupport();
support.pushContext();
support.declarePrefix("i", "http://schema.intuit.com/finance/v3");


Java (XPath):



xpath.setNamespaceContext(new NamespaceContext() {
public String getNamespaceURI(String prefix) {
switch (prefix) {
case "i": return "http://schema.intuit.com/finance/v3";
// ...
}
});



  • Remember to call
    DocumentBuilderFactory.setNamespaceAware(true).

  • See also:
    Java XPath: Queries with default namespace xmlns


xmlstarlet:



-N i="http://schema.intuit.com/finance/v3"


JavaScript:



See Implementing a User Defined Namespace Resolver:



function nsResolver(prefix) {
var ns = {
'i' : 'http://schema.intuit.com/finance/v3'
};
return ns[prefix] || null;
}
document.evaluate( '/i:IntuitResponse/i:QueryResponse',
document, nsResolver, XPathResult.ANY_TYPE,
null );


PhP:



Adapted from @Tomalak's answer using DOMDocument:



$result = new DOMDocument();
$result->loadXML($xml);

$xpath = new DOMXpath($result);
$xpath->registerNamespace("i", "http://schema.intuit.com/finance/v3");

$result = $xpath->query("/i:IntuitResponse/i:QueryResponse");


See also @IMSoP's canonical Q/A on PHP SimpleXML namespaces.



C#:



XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3");
XmlNodeList nodes = el.SelectNodes(@"/i:IntuitResponse/i:QueryResponse", nsmgr);


VBA:



xmlNS = "xmlns:i='http://schema.intuit.com/finance/v3'"
doc.setProperty "SelectionNamespaces", xmlNS
Set queryResponseElement =doc.SelectSingleNode("/i:IntuitResponse/i:QueryResponse")


VB.NET:



xmlDoc = New XmlDocument()
xmlDoc.Load("file.xml")
nsmgr = New XmlNamespaceManager(New XmlNameTable())
nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3");
nodes = xmlDoc.DocumentElement.SelectNodes("/i:IntuitResponse/i:QueryResponse",
nsmgr)


Ruby (Nokogiri):



puts doc.xpath('/i:IntuitResponse/i:QueryResponse',
'i' => "http://schema.intuit.com/finance/v3")


Note that Nokogiri supports removal of namespaces,



doc.remove_namespaces!


but see the below warnings discouraging the defeating of XML namespaces.





Once you've declared a namespace prefix, your XPath can be written to use it:



/i:IntuitResponse/i:QueryResponse




Defeating namespaces in XPath (not recommended)



An alternative is to write predicates that test against local-name():



/*[local-name()='IntuitResponse']/*[local-name()='QueryResponse']/@startPosition


Or, in XPath 2.0:



/*:IntuitResponse/*:QueryResponse/@startPosition


Skirting namespaces in this manner works but is not recommended because it




  • Under-specifies the full element/attribute name.


  • Fails to differentiate between element/attribute names in different
    namespaces (the very purpose of namespaces). Note that this concern could be addressed by adding an additional predicate to check the namespace URI explicitly1:



    /*[    namespace-uri()='http://schema.intuit.com/finance/v3' 
    and local-name()='IntuitResponse']
    /*[ namespace-uri()='http://schema.intuit.com/finance/v3'
    and local-name()='QueryResponse']
    /@startPosition


    1Thanks to Daniel Haley for the namespace-uri() note.



  • Is excessively verbose.







share|improve this answer















Defining namespaces in XPath (recommended)



XPath itself doesn't have a way to bind a namespace prefix with a namespace. Such facilities are provided by the hosting library.



It is recommended that you use those facilities and define namespace prefixes that can then be used to qualify XML element and attribute names as necessary.





Here are some of the various mechanisms which XPath hosts provide for specifying namespace prefix bindings to namespace URIs:



XSLT:



<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:i="http://schema.intuit.com/finance/v3">
...


Perl (LibXML):



my $xc = XML::LibXML::XPathContext->new($doc);
$xc->registerNs('i', 'http://schema.intuit.com/finance/v3');
my @nodes = $xc->findnodes('/i:IntuitResponse/i:QueryResponse');


Python (lxml):



from lxml import etree
f = StringIO('<IntuitResponse>...</IntuitResponse>')
doc = etree.parse(f)
r = doc.xpath('/i:IntuitResponse/i:QueryResponse',
namespaces={'i':'http://schema.intuit.com/finance/v3'})


Python (ElementTree):



namespaces = {'i': 'http://schema.intuit.com/finance/v3'}
root.findall('/i:IntuitResponse/i:QueryResponse', namespaces)


Java (SAX):



NamespaceSupport support = new NamespaceSupport();
support.pushContext();
support.declarePrefix("i", "http://schema.intuit.com/finance/v3");


Java (XPath):



xpath.setNamespaceContext(new NamespaceContext() {
public String getNamespaceURI(String prefix) {
switch (prefix) {
case "i": return "http://schema.intuit.com/finance/v3";
// ...
}
});



  • Remember to call
    DocumentBuilderFactory.setNamespaceAware(true).

  • See also:
    Java XPath: Queries with default namespace xmlns


xmlstarlet:



-N i="http://schema.intuit.com/finance/v3"


JavaScript:



See Implementing a User Defined Namespace Resolver:



function nsResolver(prefix) {
var ns = {
'i' : 'http://schema.intuit.com/finance/v3'
};
return ns[prefix] || null;
}
document.evaluate( '/i:IntuitResponse/i:QueryResponse',
document, nsResolver, XPathResult.ANY_TYPE,
null );


PhP:



Adapted from @Tomalak's answer using DOMDocument:



$result = new DOMDocument();
$result->loadXML($xml);

$xpath = new DOMXpath($result);
$xpath->registerNamespace("i", "http://schema.intuit.com/finance/v3");

$result = $xpath->query("/i:IntuitResponse/i:QueryResponse");


See also @IMSoP's canonical Q/A on PHP SimpleXML namespaces.



C#:



XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3");
XmlNodeList nodes = el.SelectNodes(@"/i:IntuitResponse/i:QueryResponse", nsmgr);


VBA:



xmlNS = "xmlns:i='http://schema.intuit.com/finance/v3'"
doc.setProperty "SelectionNamespaces", xmlNS
Set queryResponseElement =doc.SelectSingleNode("/i:IntuitResponse/i:QueryResponse")


VB.NET:



xmlDoc = New XmlDocument()
xmlDoc.Load("file.xml")
nsmgr = New XmlNamespaceManager(New XmlNameTable())
nsmgr.AddNamespace("i", "http://schema.intuit.com/finance/v3");
nodes = xmlDoc.DocumentElement.SelectNodes("/i:IntuitResponse/i:QueryResponse",
nsmgr)


Ruby (Nokogiri):



puts doc.xpath('/i:IntuitResponse/i:QueryResponse',
'i' => "http://schema.intuit.com/finance/v3")


Note that Nokogiri supports removal of namespaces,



doc.remove_namespaces!


but see the below warnings discouraging the defeating of XML namespaces.





Once you've declared a namespace prefix, your XPath can be written to use it:



/i:IntuitResponse/i:QueryResponse




Defeating namespaces in XPath (not recommended)



An alternative is to write predicates that test against local-name():



/*[local-name()='IntuitResponse']/*[local-name()='QueryResponse']/@startPosition


Or, in XPath 2.0:



/*:IntuitResponse/*:QueryResponse/@startPosition


Skirting namespaces in this manner works but is not recommended because it




  • Under-specifies the full element/attribute name.


  • Fails to differentiate between element/attribute names in different
    namespaces (the very purpose of namespaces). Note that this concern could be addressed by adding an additional predicate to check the namespace URI explicitly1:



    /*[    namespace-uri()='http://schema.intuit.com/finance/v3' 
    and local-name()='IntuitResponse']
    /*[ namespace-uri()='http://schema.intuit.com/finance/v3'
    and local-name()='QueryResponse']
    /@startPosition


    1Thanks to Daniel Haley for the namespace-uri() note.



  • Is excessively verbose.








share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 27 at 20:03

























answered Nov 25 '16 at 0:58









kjhugheskjhughes

67.6k1394134




67.6k1394134













  • Thank you for such a complete answer. One thing I still don't understand though is how when I use a library like Javax or Pugi XML to parse the XML above with the path I specified, I actually do get results (i.e. a node list) back. Do some of these libraries have an ability to somehow infer simple namespaces?

    – Adam
    Nov 25 '16 at 17:42








  • 1





    pugi: nonconformance declaration in docs + odd behavior observation = turn and run / life's too short. Javax: Don't forget to call setNamespaceAware(true) on the DocumentBuilderFactory.

    – kjhughes
    Nov 25 '16 at 19:56








  • 2





    Turns out pugixml doesn't support xml namespaces at all (stackoverflow.com/questions/1042855/…). Turning and running.

    – Adam
    Nov 25 '16 at 21:10








  • 1





    @DougGlancy: Sorry, VBA was one of the few examples I'd not yet provided. Remedied by adding now. Note that unqualified attribute names are not automatically placed in the default namespace specified on ancestor elements. I've reopened your other question since other than this detail, you'd already accounted for namespaces properly. Let me know here if I can help in general with XPath and namespaces or over on your question if particular to that issue. Thanks.

    – kjhughes
    Nov 20 '17 at 4:09








  • 1





    Thanks, very helpful.

    – Doug Glancy
    Nov 20 '17 at 4:18



















  • Thank you for such a complete answer. One thing I still don't understand though is how when I use a library like Javax or Pugi XML to parse the XML above with the path I specified, I actually do get results (i.e. a node list) back. Do some of these libraries have an ability to somehow infer simple namespaces?

    – Adam
    Nov 25 '16 at 17:42








  • 1





    pugi: nonconformance declaration in docs + odd behavior observation = turn and run / life's too short. Javax: Don't forget to call setNamespaceAware(true) on the DocumentBuilderFactory.

    – kjhughes
    Nov 25 '16 at 19:56








  • 2





    Turns out pugixml doesn't support xml namespaces at all (stackoverflow.com/questions/1042855/…). Turning and running.

    – Adam
    Nov 25 '16 at 21:10








  • 1





    @DougGlancy: Sorry, VBA was one of the few examples I'd not yet provided. Remedied by adding now. Note that unqualified attribute names are not automatically placed in the default namespace specified on ancestor elements. I've reopened your other question since other than this detail, you'd already accounted for namespaces properly. Let me know here if I can help in general with XPath and namespaces or over on your question if particular to that issue. Thanks.

    – kjhughes
    Nov 20 '17 at 4:09








  • 1





    Thanks, very helpful.

    – Doug Glancy
    Nov 20 '17 at 4:18

















Thank you for such a complete answer. One thing I still don't understand though is how when I use a library like Javax or Pugi XML to parse the XML above with the path I specified, I actually do get results (i.e. a node list) back. Do some of these libraries have an ability to somehow infer simple namespaces?

– Adam
Nov 25 '16 at 17:42







Thank you for such a complete answer. One thing I still don't understand though is how when I use a library like Javax or Pugi XML to parse the XML above with the path I specified, I actually do get results (i.e. a node list) back. Do some of these libraries have an ability to somehow infer simple namespaces?

– Adam
Nov 25 '16 at 17:42






1




1





pugi: nonconformance declaration in docs + odd behavior observation = turn and run / life's too short. Javax: Don't forget to call setNamespaceAware(true) on the DocumentBuilderFactory.

– kjhughes
Nov 25 '16 at 19:56







pugi: nonconformance declaration in docs + odd behavior observation = turn and run / life's too short. Javax: Don't forget to call setNamespaceAware(true) on the DocumentBuilderFactory.

– kjhughes
Nov 25 '16 at 19:56






2




2





Turns out pugixml doesn't support xml namespaces at all (stackoverflow.com/questions/1042855/…). Turning and running.

– Adam
Nov 25 '16 at 21:10







Turns out pugixml doesn't support xml namespaces at all (stackoverflow.com/questions/1042855/…). Turning and running.

– Adam
Nov 25 '16 at 21:10






1




1





@DougGlancy: Sorry, VBA was one of the few examples I'd not yet provided. Remedied by adding now. Note that unqualified attribute names are not automatically placed in the default namespace specified on ancestor elements. I've reopened your other question since other than this detail, you'd already accounted for namespaces properly. Let me know here if I can help in general with XPath and namespaces or over on your question if particular to that issue. Thanks.

– kjhughes
Nov 20 '17 at 4:09







@DougGlancy: Sorry, VBA was one of the few examples I'd not yet provided. Remedied by adding now. Note that unqualified attribute names are not automatically placed in the default namespace specified on ancestor elements. I've reopened your other question since other than this detail, you'd already accounted for namespaces properly. Let me know here if I can help in general with XPath and namespaces or over on your question if particular to that issue. Thanks.

– kjhughes
Nov 20 '17 at 4:09






1




1





Thanks, very helpful.

– Doug Glancy
Nov 20 '17 at 4:18





Thanks, very helpful.

– Doug Glancy
Nov 20 '17 at 4:18




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f40796231%2fhow-does-xpath-deal-with-xml-namespaces%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Academy of Television Arts & Sciences

L'Équipe

1995 France bombings