-->

Declare namespaces within XPath expression

2019-02-23 12:46发布

问题:

My application needs to evaluate XPath expression against some XML data. Expression is provided by user at runtime. So, I cannot create XmlNamespaceManager to pass to XPathEvaluate because I don't know prefixes and namespaces at compile time.

Is there any possibility to specify namespaces declaration within xpath expression?


Answers to comments:

  1. XML data has one default namespace but there can be nested elements with any namespaces. User knows namespaces of the data he works with.
  2. User-provided xpath expression is to be evaluated against many XML documents, and every document can have its own prefixes for the same namespaces.

回答1:

I don't know any way to define a namespace prefix in an XPath expression.

But you can write the XPath expression to be agnostic of namespace-prefixes by using local-name() and namespace-uri() functions where appropriate.

Or if you know the XML-namespaces in advance, you can register an arbitrary prefix for them in the XmlNamespaceManager and tell your user to use that prefix in the XPath expression. It doesn't matter if the XML document itself registers a different prefix or no prefix at all. Path resolution is based on the namespace alone, not on the prefix.

Another option would be to scan the document at runtime (use XmlReader for low resource overhead if you haven't loaded it already) and then add the used mappings in the document in the XmlNamespaceManager. I'm not sure if you can get the namespaces and prefixes from XmlDocument, but I see no direct method to do it. It's easy with XmlReader though, since it exposes NamespaceURI and Prefix members for each node.



回答2:

If the same prefix can be bound to different namespaces and prefixes aren't known in advance, then the only pure XPath way to specify such expressions is to use this form of referring to elements:

someName[namespace-uri() = 'exactNamespace']

So, a particular XPath expression would be:

/*/a[namespace-uri() = 'defaultNS']/b[namespace-uri() = 'NSB']
                                         /c[namespace-uri() = 'defaultNS']


回答3:

Is there any possibility to specify namespaces declaration within xpath expression?

The answer is no - it's always done in the calling environment (which is actually more flexible).

An alternative would be to use XQuery, which does allow declaring namespaces in the query prolog.