xpath expression from xml with namespace prefix
Asked Answered
C

2

19

I could not get the following xpath expression to work when the xml path namespace prefix set.

/bk:BookStore/bk:Books/bk:Book[text()='Time Machine']

XML is:

<BookStore xmlns:bk="http://www.bookstore.com/book#">
  <bk:Books>
    <bk:Book id="1">Time Machine></bk:Book>
  </bk:Books>
</bk:BookStore>
Compossible answered 14/10, 2010 at 9:31 Comment(2)
Post the code that executes the XPath query.Nichollenicholls
You need to pass the prefix/namespace-URI binding to your XPath engine. Why? Because prefixes are not important for name test, but namespace URI are. So a:node could select b:node as long as a and b prefixes are binding to the same namespace URI.Surname
D
19

Without more information about the host language (in which you attempt to evaluate XPath expressions) it is not possible to provide an useful recommendation.

Generally, one needs to "register" a namespace with a namespace manager and this also associates a prefix to the registered namespace. Then, using this NamespaceManager object as an argument to the XPath-evaluation method, one can specify as argument to this method an XPath expression that contains names prefixed by that particular prefix.

Workarounds:

/*/*[name()='bk:Books']/*[name()='bk:Book' and text()='Time Machine']
Dennadennard answered 14/10, 2010 at 18:1 Comment(4)
I am using xml signature in java. I wan to select the elements to be signed using xpath in the trasnforms section. How do I give the xpath expression when I have prefixes and namespaces in my xml document.Keratogenous
@Ashwin: This answer shows exactly how to do this (one of the possible ways), without registering namespaces. The second possible way is to register the namespace to prefix bindings in which element names referenced in the XPath expression are -- then the XPath expression can contain prefixes and be more readable. This second way requires to use for the namespace registering implementation-provided APIs and one needs to read the appropriate documentation.Dennadennard
More proper 'workaround' is something like: //*[fn:namespace-uri()="http://www.bookstore.com/book#" and local-name()='Book']. Actually, it is not even a workaround, just a verbose xpath. For brevity there are the prefixes and the environment that you use to execute xpath should provide you with a way of specifying them (the prefixes used in the xpath can be different from those used in the XML file).Craggie
@DavidL.This is a useful workaround. However, it hardcodes the namespace-uri and must always be modified, if the namespace itself is modified. Imagine having to maintain many such expressions. The advantage of using a specific namespace prefix is that in such cases only a single modification would be necessary.Dennadennard
A
40

Or even better (and more portable), without the unnecessary prefix:

/*/*[local-name()='Books'] ... and so on

The function local-name ignores any prefix, which, as correctly stated by commenters, can vary.

Aveyron answered 18/11, 2011 at 11:14 Comment(2)
Why did someone downvote this? I found this an excellent solution to avoid dealing with namespaces, which are just annoying and unnecessary 99% of the time.Lemoine
If the namespaces are just a hurdle you have to get past, imposed on you externally -- as they often are -- then this is definitely the way to go.Binocular
D
19

Without more information about the host language (in which you attempt to evaluate XPath expressions) it is not possible to provide an useful recommendation.

Generally, one needs to "register" a namespace with a namespace manager and this also associates a prefix to the registered namespace. Then, using this NamespaceManager object as an argument to the XPath-evaluation method, one can specify as argument to this method an XPath expression that contains names prefixed by that particular prefix.

Workarounds:

/*/*[name()='bk:Books']/*[name()='bk:Book' and text()='Time Machine']
Dennadennard answered 14/10, 2010 at 18:1 Comment(4)
I am using xml signature in java. I wan to select the elements to be signed using xpath in the trasnforms section. How do I give the xpath expression when I have prefixes and namespaces in my xml document.Keratogenous
@Ashwin: This answer shows exactly how to do this (one of the possible ways), without registering namespaces. The second possible way is to register the namespace to prefix bindings in which element names referenced in the XPath expression are -- then the XPath expression can contain prefixes and be more readable. This second way requires to use for the namespace registering implementation-provided APIs and one needs to read the appropriate documentation.Dennadennard
More proper 'workaround' is something like: //*[fn:namespace-uri()="http://www.bookstore.com/book#" and local-name()='Book']. Actually, it is not even a workaround, just a verbose xpath. For brevity there are the prefixes and the environment that you use to execute xpath should provide you with a way of specifying them (the prefixes used in the xpath can be different from those used in the XML file).Craggie
@DavidL.This is a useful workaround. However, it hardcodes the namespace-uri and must always be modified, if the namespace itself is modified. Imagine having to maintain many such expressions. The advantage of using a specific namespace prefix is that in such cases only a single modification would be necessary.Dennadennard

© 2022 - 2024 — McMap. All rights reserved.