Using XSLT, I'm wondering how to get the output to use my stylesheet's namespace prefixes rather than the input document's prefixes. By way of example, given this very simplified document:
<?xml version="1.0"?>
<a:node xmlns:a="urn:schemas:blah:"/>
And the following XSL transform:
<?xml version="1.0"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:blah="urn:schemas:blah:" version="2.0">
<xsl:output indent="yes">
<xsl:template match="/blah:node">
<xsl:copy/><!-- marked -->
</xsl:template>
</xsl:transform>
I can tell that the processor (Saxon8 if it matters) recognizes the equivalence of the prefixes 'blah:' and 'a:', but fn:in-scope-prefixes() for example doesn't show 'blah', only 'a'. Changing the <!-- marked -->
line above to:
<node><xsl:value-of select="in-scope-prefixes(.)"/></node>
Outputs:
<?xml version="1.0" encoding="UTF-8"?>
<node xmlns:blah="urn:schemas:blah:">xml a</node>
How can I map the input prefix 'a' to 'blah' without knowing in advance that the input file calls that prefix 'a'? (So <xsl:namespace-alias/>
won't work for me.)
As further context, if it points toward a better solution, this is for viewing XML documents that are generated externally. The external process creates the input document using automatically-generated prefixes 'a:', 'b:', 'c:', etc. I want to be able to display those prefixes using 'friendlier' namespace prefixes.
Update: The in-scope-prefixes() behavior is explained by the definition of Statically known namespaces
This transformation (both in XSLT 1.0 and XSLT 2.0 (just change the version
attribute)) :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:namespaces>
<ns prefix="blah" uri="urn:schemas:blah:"/>
<ns prefix="foo" uri="uff:anotherNamespace"/>
</my:namespaces>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[namespace-uri()=document('')/*/my:namespaces/*/@uri]">
<xsl:variable name="vNS" select=
"document('')/*/my:namespaces/*
[@uri=namespace-uri(current())]"/>
<xsl:element name="{$vNS/@prefix}:{local-name()}"
namespace="{namespace-uri()}">
<xsl:copy-of select=
"namespace::*[not(. = namespace-uri(current()))]"/>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Copies any XML document and only replaces the prefixes this document uses for select namespaces with the prefixes we have specified.
when applied on this XML document:
<t>
<a:node xmlns:a="urn:schemas:blah:"/>
<b:node xmlns:b="urn:schemas:blah:"/>
<c:node xmlns:c="uff:anotherNamespace"/>
</t>
the wanted result is produced:
<t>
<blah:node xmlns:blah="urn:schemas:blah:"/>
<blah:node xmlns:blah="urn:schemas:blah:"/>
<foo:node xmlns:foo="uff:anotherNamespace"/>
</t>