Question

I have an XSLT stylesheet that needs to emit an XML fragment that looks like this (the "..." bits are elided for brevity) :

<MyOuterType xmlns:xsi="..." xsi:type="foo:MyInnerType" xmlns:foo="..."/>

The stylesheet looks like this :

<xsl:stylesheet xmlns:foo="..." xmlns:xsi="...">
  ...
  <xsl:template match="...">
    <xsl:element name="MyOuterType">
      <xsl:attribute name="xsi:type">foo:MyInnerType</xsl:attribute>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

The XSLT processor's output looks like this :

<MyOuterType xmlns:xsi="..." xsi:type="foo:MyInnerType"/>

In other words, it's missing the xmlns:foo declaration. In fact the declaration is completely absent from the emitted XML, despite it being declared in the stylesheet. This messes things up later, when I need to deserialize the emitted XML.

How can I get my xmlns:foo to appear in the emitted XML? The processor implements XSLT 1.0.

Was it helpful?

Solution

It depends whether you know the namespace you want to generate statically, or whether it's based on information in the input document.

If you know it statically, just use a literal result element instead of xsl:element:

<MyOuterType xsi:type="foo:MyInnerType" xmlns:foo="....."/>

If it's a dynamic decision, it's a bit more complicated. XSLT 2.0 has an xsl:namespace instruction to generate namespaces in much the same way that xsl:attribute generates attributes. In XSLT 1.0, the trick is to create an element that contains the required namespace, and then use xsl:copy to copy the namespace node:

<xsl:variable name="dummy">
  <xsl:element name="foo:dummy" namespace="{$param}"/>
</xsl:variable>
<MyOuterType xsi:type="foo:MyInnerType">
  <xsl:copy-of select="exsl:node-set($dummy)/*/namespace::foo"/>
</MyOuterType>

Unfortunately there are one or two not-quite-XSLT-1.0 processors out there that don't implement namespace nodes correctly, so exercise caution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top