I am writing an XSL template that pulls data from many secondary sources. An example secondary document looks like this:
<toplevel xmlns:foo1="http://foo1">
<path xmlns="http://foo1">
<mytag>bar</mytag>
</path>
</toplevel>
In the XSL, I am doing this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:foo1="http://foo1"
exclude-result-prefixes="foo1">
<xsl:variable name="secondary1" select="document('secondary1.xml')/toplevel"/>
<foo>
<xsl:value-of select="$secondary1//foo1:path/foo1:mytag"/>
</foo>
</xsl:stylesheet>
With a lot of secondary sources, each of which uses a different namespace, prefixing every single tag is tedious, and that much repetition can't be the right thing to do anyway. Is there a way to use document() such that the namespace of the imported node-set is stripped (or to achieve the same effect another way)?
In essence, a node with a namespace is an entirely different animal than a node with another namespace - even if they happen to share the same local name. (This is much the same way namespaces work everywhere else - there is really no easy way of "ignoring" namespaces. Think of ignoring namespaces when referring to classes in C#.)
The clean approach would be to mention each namespace you might encounter in the XSLT and work with prefixes, even if it seems repetitive.
The not-so-clean way is this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:variable name="secondary1" select="document('secondary1.xml')"/>
<xsl:template match="/">
<foo source="1">
<xsl:value-of select="
$secondary1//*[local-name() = 'path']/*[local-name() = 'mytag']
"/>
</foo>
</xsl:template>
</xsl:stylesheet>
This is not really more pleasing to the eye than working with prefixes, it's longer and harder to read, it is ambiguous, and last but not least - it is slower because the engine must test a predicate on every step on the XPath. Take your pick.