3
votes

I have a simple xml node, and an equally simple xpath query expression, but it's not working properly. I've tried all sorts of variations on it (//node-name, *[name()='node-name'], current-node-name/node-name), but it's still not finding the correct node!

Here's my xml:

<page-reference xmlns="http://something.com">
  <relative-path>something/something</relative-path>
  <base-path>somePath</base-path>
</page-reference>

I've tried a few different variations of x-paths. Most of them work if I take out the xmlns attribute of the page-reference tag. For example: //relative-path, /page-reference/relative-path, relative-path, page-reference/relative-path, but none of them work with the xmlns attribute.

Any ideas what could be causing this? I thought that it's the double slash after the http in the value, but I have no idea why that would cause an issue, and it also does not seem to be the case.

3
What language are you using to parse/invoke the XPath on the XML?Mendhak
@Shah I'm using Javascript for my real application. I'm also doing testing using xpathtester.com/test to test my xpath with the xml in my node. They are both not retrieving any resultschama

3 Answers

2
votes

Or, alternatively, you could use:

//*[name()='relative-path']
2
votes

The xmlns attribute provides a namespace for the element, meaning it is not just a normal "page-reference" or "relative-path" element, so it cannot be accessed as such. Different languages have different ways of indicating the namespace, from indicating the default for your XPath queries to using prefixes.

For JavaScript, you can use a namespace resolver: https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript#Implementing_a_User_Defined_Namespace_Resolver (if you want to specify prefixes--useful when there are different namespaces used within the document) and/or to rely on a default namespace within XPath expressions (though you need to use some--ANY--prefix): https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript#Implementing_a_default_namespace_for_XML_documents

var xml = new DOMParser().parseFromString('<page-reference xmlns="http://something.com">'+
  '<relative-path>something/something</relative-path>'+
  '<base-path>somePath</base-path>'+
'</page-reference>', 'text/xml');

function resolver() {
    return 'http://something.com';
}
var refs = xml.evaluate('//x:page-reference', xml, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
alert(refs.snapshotItem(0).nodeName) // 'page-reference'

You'll need a shim for IE support. (A quick search turned up http://sourceforge.net/projects/js-xpath/files/js-xpath/ )

1
votes

XPath is not aware of a "default" XML namespace (xmlns). As a result, you'll need to prefix all of your nodes in your XPath expressions with the page-reference tag's namespace.

XML:

<page-reference xmlns:s="http://something.com">
  <relative-path>something/something</relative-path>
  <base-path>somePath</base-path>
</page-reference>

XPath:

//s:relative-path