views:

917

answers:

4

I have a XSLT I've created to handle a particular xml document. However, now namespaces are being introduced in some, but not all of our documents. I'd like to use the same XSLT for these documents, however I'm having trouble modifying my stylesheet to be namespace agnostic.

It's been suggested previously to modify my xpaths to *[local-name()="ElementName"], however considering we've already made a stylesheet, this is very labor intensive.

In addition, I am aware I can set the xpath-default-namespace to the particular namespace, but as mentioned earlier, I cannot simply set it to #all or a list of possible namespaces. I'm looking for a more effective solution and have the extension functions of the Saxon processor available to me. Any ideas? Thanks.

+1  A: 

After further consultation, it seems that there simply is no easy way out of this. The XSLT must be redesigned to be namespace agnostic, or use the xpath-default-namespace attribute on the <xsl:stylesheet> element. If we wish to preserve the namespace of the incoming document but still have one stylesheet work with multiple namespaces then our templates would need to resemble the following form:

<xsl:template match="*[local-name(.)='ElementName']">
   <xsl:element name="{local-name(.)}" xmlns="http://yourURIhere"&gt;
      <xsl:value-of select="."/>
   </xsl:element>
</xsl:template/>

etc.

Jweede
+3  A: 

Have you considered pre-processing your XML documents?

You could remove all namespaces (be aware of possible clashes) and then process it using the existing XSL transformation.

Such an approach would have the advantage that you don't have to modify your XSLT at all. It stays readable (the *[local-name()='frob'] looks so awful) and maintainable.

0xA3
This is what we ended up doing to mitigate the namespace problem temporarily. I agree the *[local-name() stuff is not very elegant. Thanks for helping out!
Jweede
+1  A: 

Maybe I don't understand your problem, but couldn't you just have your template(s) match both the null-namespace version and the namespaced version of the element? - Like this:

<xsl:template match="ElementName | NS:ElementName" xmlns:NS="your-namespace">
   ... output ...
</xsl:template>

(Typically the declaration of the NS prefix would be placed on the stylesheet element)

This is by far the most 'clean' version to me - I've beeen using this to have a single XSLT stylesheet process all three RSS formats (0.91, 1.0 & 2.0).

greystate
This is a good solution, although it still involves rewriting the complex template. Thanks for helping out!
Jweede
A: 

I disagree.

Just changes every node name to be "*:Element"

If you're really skilled you can write a perl script to just run on your code to change it for you.

iceandrews