XSLT: Normalizing namespaces

T

Thomas Wittek

Hi!

Suppose I have to handle documents with the same schema [1] but some
instances use a (proper) namespace and some instances just use the
default (empty) namespace.

Examples:

<doc xmlns="urn:some_ns">
<foo>bar</foo>
</doc>

<doc>
<foo>bar</foo>
</doc>

Currently I have to write each template like this:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:somens="urn:some_ns">

<xsl:template match="foo | somens:foo" />

</xsl:stylesheet>

That's quite tedious to do for each and every XPath selection.

I could imagine a modified identity transformation that changes the
namespace for a given document.
But then I have to run two XLSTs consecutively, whereas I would prefer
to have the transformation in *one* file.

So is there any possibilty to normalize the namespace of the input
document instead of preprocessing it with another XSLT? Or override the
default namespace of the input doc?

Thank you for any ideas!

[1] Or at least the same structure.
Obviously the doc without the namespace cannot use the same
"XML Schema" becaus it's not in the correct namespace.
 
J

Joseph Kesselman

Thomas said:
<doc xmlns="urn:some_ns">
<foo>bar</foo>
</doc>

<doc>
<foo>bar</foo>
</doc>

The whole point of namespaces is that those two documents have different
semantic meanings. You can't, and shouldn't "normalize" them.

If you really insist on ignoring these differences your choices are
either to explicitly match all the possibilities:
<xsl:template match="foo | somens:foo" />

or to write patterns that match on things like *[localname(.)='foo'].
The latter which will get you either laughed at or screamed at by folks
who understand the intent of namespaces.
 
T

Thomas Wittek

Joseph said:
The whole point of namespaces is that those two documents have different
semantic meanings. You can't, and shouldn't "normalize" them.

Of course. But in this case the docs have perfectly the same semantics.
The only difference is that on some docs the generator didn't specify
the namespace.
If you really insist on ignoring these differences your choices are
either to explicitly match all the possibilities:
<xsl:template match="foo | somens:foo" />

or to write patterns that match on things like *[localname(.)='foo'].
The latter which will get you either laughed at or screamed at by folks
who understand the intent of namespaces.

:) And it's almost equally as ugly as "foo | somens:foo".

The best solution might be adding the missing namespace to the docs.
But this would add an inconvenient preprocessing step.
Having it all in one XSLT would be nice.
 
T

Thomas Wittek

Thomas said:
The best solution might be adding the missing namespace to the docs.
But this would add an inconvenient preprocessing step.
Having it all in one XSLT would be nice.

Suppose I'd do that.
Hm, would I miss anything but the comment and pi nodes using this
"identity" transformation to a new namespace "foo"?

<xsl:template match="*">
<xsl:choose>
<!-- don't overwrite existing namespaces -->
<xsl:when test="namespace-uri()">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:when>
<xsl:eek:therwise>
<xsl:element name="{name()}" namespace="urn:foo">
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:element>
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

The identity transformations I've seen are a bit different.
As I'm quite new to XSLT I'm not sure, if I miss anything with the code
above.

Maybe it would be easier to just "somehow" (DOM, regexp) add a default
namespace to those documents...
 
J

Joseph Kesselman

Thomas said:
Of course. But in this case the docs have perfectly the same semantics.
The only difference is that on some docs the generator didn't specify
the namespace.

And thus changed the semantics. That generator is misusing XML; fix
and/or educate it.
The best solution might be adding the missing namespace to the docs.

The _best_ solution involves not producing broken documents. Insist they
say what they meant, rather than trying to guess what was meant. You'll
be doing both them and yourself a favor in the long run.
 
M

Martin Honnen

Thomas said:
<xsl:template match="foo | somens:foo" />

That's quite tedious to do for each and every XPath selection.

With XSLT/XPath 2.0 you could use a wildcard * for the prefix e.g.
<xsl:template match="*:foo">
matches elements with local name foo in any namespace (including no
namespace).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top