first_page the funky knowledge base
personal notes from way, _way_ back and maybe today

XSLT: “XPath and Default Namespace handling”

Now let's take the same XML however now defining all elements in the 'http://www.edankert.com/examples/' namespace.

And instead of prefixing all the different elements (although this would cause the same problem), we're declaring a so-called default namespace at the root element.

So the XML now looks like:

<catalog x­mlns="http://www.edankert.com/examples/"> <cd> <artist>Sufjan Stevens</artist> <title>Illinois</title> <src>http://www.sufjan.com/</src> </cd> <cd> <artist>Stoat</artist> <title>Future come and get me</title> <src>http://www.stoatmusic.com/</src> </cd> <cd> <artist>The White Stripes</artist> <title>Get behind me satan</title> <src>http://www.whitestripes.com/</src> </cd> </catalog>

When we now use the same XPath as above '//cd', we notice that nothing is returned. This is because the specified XPath returns all cd elements that have not been declared in a namespace and in the example above all the 'cd' elements are declared in the 'http://www.edankert.com/examples/' namespace. Namespace-Prefix mappings

We need some kind of way to specify in our XPath expression that we are looking for all 'cd' elements in the 'http://www.edankert.com/examples/' namespace.

To handle this, the XPath specification allows us to use a QName to specify an element or an attribute. A QName can be either a name on its own 'element' or a name with a prefix 'pre:element'. This prefix however needs to be mapped to a Namespace URI. So mapping the 'pre' prefix to the 'http://www.edankert.com/test' Namespace URI should allow us to find all 'element' elements defined in the 'http://www.edankert.com/test' namespace.

In this case for instance we could use the 'edx' prefix and map this prefix to the 'http://www.edankert.com/examples/' namespace URI. This would result in the following XPath expression that should return all 'cd' elements that are declared in the 'http://www.edankert.com/examples/' namespace: '//edx:cd'.

All XPath processors allow you to specify prefix-namespace mappings, however how depends on the specific implementation. See below for examples of how to map namespaces and prefixes using Jaxen (JDOM/dom4j/XOM), JAXP and XSLT.

XPath was originally designed to be used with XSLT, this (and maybe because XSLT is an XML vocabulary) might explain why declaring prefix namespace-uri mappings in XSLT seems very natural.

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="//edx:cd" xmlns:edx="http://www.edankert.com/examples/"> <xsl:apply-templates/> </xsl:template> </xsl:stylesheet>

To specify the prefix namespace-uri we can simply specify a namespace-uri for the 'edx' prefix, using the normal XML mechanism.

To get the same output as for the previous examples, we can use a xsl:template that matches our //edx:cd XPath expression.

Conclusion

So, to be able to use XPath expressions on XML content defined in a (default) namespace, we need to specify a namespace prefix mapping. As we have seen, it does not matter what prefix the namespace is mapped to.

[http://www.edankert.com/defaultnamespaces.html]

mod date: 2009-08-27T17:24:25.000Z