views:

170

answers:

3

I need to add an xmlns to the root element in the output of this XSLT transform. I've tried added <xsl:attribute name="xmlns"> but it's disallowed.

Has anyone got any ideas how I could solve this?

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

    <xsl:template match="/">
      <xsl:variable name="rootElement" select="name(*)"/>
      <xsl:element name="{$rootElement}">
       <xsl:apply-templates select="/*/*"/>
      </xsl:element>
    </xsl:template>

    <xsl:template match="node()"> 
        <xsl:copy> 
       <xsl:copy-of select="@*"/> 
            <xsl:apply-templates select="node()"/> 
        </xsl:copy> 
    </xsl:template>

</xsl:stylesheet>
+3  A: 

From the XSLT 1.0 spec:

The xsl:element element allows an element to be created with a computed name. The expanded-name of the element to be created is specified by a required name attribute and an optional namespace attribute.

So you need to declare the namespace prefix you wish to use on your xsl:stylesheet element, and then specify the namespace URI when you create the element.

To illustrate, the following stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:foo="http://example.com/foo"&gt;
  <xsl:template match="/">
    <xsl:element name="bar" namespace="http://example.com/foo"&gt;element&lt;/xsl:element&gt;
  </xsl:template>
</xsl:stylesheet>

produces the output:

<?xml version="1.0" encoding="UTF-8"?>
<foo:bar xmlns:foo="http://example.com/foo"&gt;element&lt;/foo:bar&gt;
NickFitz
+1  A: 

You can't simply "add" a namespace, at least not in XSLT 1.0. Namespaces are fixed properties of the input nodes. You copy the node, you copy its namespace as well.

This means you'd have do create new nodes in the correct namespace. If you don't want a prefix, but a default namespace instead, the XSL stylesheet has to be in the same default namespace.

The following applies the default namespace to all element nodes and copies the rest:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="http://tempuri.org/some/namespace"
>

  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="node() | @*" />
    </xsl:element> 
  </xsl:template>

</xsl:stylesheet>

turning

<bla bla="bla">
  <bla />
</bla>

to

<bla bla="bla" xmlns="http://tempuri.org/some/namespace"&gt;
  <bla></bla>
</bla>
Tomalak
A: 

Read this excellent article. It covers both XSLT 1.0 and 2.0

Alexander Pogrebnyak