OK, let's break it down step by step...

The three arguments to this version of the XPathAPI calls are:

1) contextNode: The DOM Node from which the XPath should begin its
navigation.

2) The XPath, as a Java String. Names in this XPath may use namespace
prefixes.

3) namespaceNode: A DOM node (typically, but not necessarily, an Element)
which is used to provide the namespace context for this XPath. This is used
to convert the prefixes in the XPath string to namespace URIs before the
XPath is executed. We do this by looking at the namespaces declared on this
node, or inherited from its ancestors. Note that the namespaceNode does
_NOT_ have to belong to the document you are going to search -- a typical
example would be an XPath specified as part of an XSLT stylesheet
directive, where the namespace node is generally the stylesheet element
which carries that match or select request.


Let's try an example: Apply the xpath "//myPrefix:a/@which"  to  any node
in the following document:

      <root xmlns:myPrefix="http://www.apache.org/myFirstNamespace";>
            <myPrefix:a which="first">
            <myPrefix:a xmlns:myPrefix
="http://www.apache.org/mySecondNamespace"; which="second"/>
      </root>

Start with the simple case where the namespaceNode is the <root> element.
To understand what "myPrefix:" means in the XPath, we look at the
contextNode  and see whether it defines this prefix. It does
(....myFirstNamespace), so the XPath will look for an element with that
namespace and the localname a -- the first one, since it inherited this
prefix definition from its parent -- retrieve its attribute and return
"first".

The same thing would happen if the namespaceNode was the first <myPrefix:a>
element. We look at it, see that it inherited the prefix definition from
the root, use that namespace, and produce the same result.

Now, what if the namespaceNode was the _second_ <myPrefix:a?> Here, a
different definition of the prefix is in effect (...mySecondNamespace), so
the XPath would go looking for that namespace instead... and would find
this node.


But, as I said, the namespaceNode doesn't have to be in the same document
that you're searching, or even in the same DOM implementation. If I had a
completely separate DOM Element object which had an appropriate prefix
definition element, I could use that and have the same result. This gives
you a way to set up a completely arbitrary mapping for namespace prefixes
in an XPath; just construct an Element (eg, using the Xerces DOM) which
defines them appropriately and plug it into the call.  Xalan's XSLT
processor does very much this sort of thing; XPaths in XSLT have their
namespace prefixes interpreted in the context of the stylesheet element
that's invoking them.


NOTE: The XPath 1.0 syntax has no equivalent of the default namespace
declaration. Given a document such as

      <root xmlns="http://www.apache.org/myFirstNamespace>
            <a which="first">
      </root>

you still have to use the same sort of XPath shown above, with a prefix,
and provide a namespaceNode which maps that prefix to ....myFirstNamespace.
If you don't provide a prefix, XPath 1.0 assumes that you mean the node
should have _NO_ namespace, and it won't match the <a> node shown here
since that does have an implied namespace. (XPath 2.0 is considering
providing a way to set the default namespace for an XPath, to avoid this
bit of confusion... but that's still a Working Draft, and Xalan hasn't yet
prototyped that feature.)



One final point: You mentioned "I tried creating the elements with
createElementNS" -- you ***MUST*** use that call (and createAttributeNS) to
create DOMs that you want to apply Xalan's XPath and XSLT APIs to. The old
DOM Level 1 createElement() and createAttribute() calls are considered
obsolete, and nodes created using them are generally not compatable with
namespace-aware applications such as Xalan.


______________________________________
Joe Kesselman  / IBM Research


Reply via email to