Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Well, it turns out that there is no standard way to get this XPath to work:

    /data/a 

Apparently, there There is no XPath 1.0-standard mechanism for associating an unqualified XPath path step, (such as 'data' or 'a' in the path) to be implicitly qualified by a namespace. This path can only work if the data has no namespace specifieda namespace with a prefix (or with the default namespace).  Such mechanisms are specific to the XPath-1.0 processor.

Things that work

There are a few ways to deal with this problem.

0) Bind the namespaces using the XPath-1.0 processor

XPath-1.0 processors typically provide a way to bind namespace external to the XPath 1.0 expression.  For example, in JAXB, namespaces are bound to prefixes (and to the default namespace) using the http://docs.oracle.com/javase/7/docs/api/javax/xml/xpath/XPath.html#setNamespaceContext(javax.xml.namespace.NamespaceContext) method.  See http://docs.oracle.com/javase/7/docs/api/index.html?javax/xml/xpath/XPath.html and the discussion on QNames in the class overview. Also see http://docs.oracle.com/javase/7/docs/api/javax/xml/namespace/NamespaceContext.html for details on how to bind the default namespace.

1) Avoid Namespaces

If you have all non-qualfied elements with none of these xmlns="..." things around like this:

...

well, this works fine with the XPath /data/a.

 

2) Prefix All Element Names:

You can qualify every element. This is in some sense the most robust approach. So if you write:

 

<tns:data xmlns:tns="urn:someNamespaceOrOther"><tns:a>75</tns:a></tns:data>

...

/tns:data/tns:a 

is meaningful and works.  However, for an XPath-1.0 processor, the tns prefix will need to be bound before the XPath expression will evaluate successfully.  See option (0) above for details.  (Note that this path will work without any hassle in an XPath-2.0 processor.)

3) Use Both Non-Qualfied Names and a Prefix

...

/tns:data/tns:a

also works in this case.  Again, see note above on binding namespaces.

4) Match the namespace and/or the local-name of the element in the XPath expression

For the original example, this XPath 1.0 expression should work:

/*[local-name() = 'data' and namespace() = 'urn:someNamespaceOrOther']/*[local-name() = 'a' and namespace() = 'urn:someNamespaceOrOther']

Summary

There are several ways to get namespaces to work with XPath 1.0, but none of them are pretty or elegant.