tags:

views:

29

answers:

2

Hi,

How can I transform nested XML elements with xslt, keeping the structure?

Let's say I have an XML document like this:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <node>
  </node>
  <node>
    <node>
      <node>
      </node>
    </node>
  </node>
</root>

And I would like to get something like this:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <element>
    </element>
    <element>
      <element>
        <element>
        </element>
      </element>
    </element>
</root>

What kind of xslt should I use?

Thanks!

+2  A: 
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  <xsl:template match="/root">
    <root>
      <xsl:apply-templates />
    </root>
  </xsl:template>
  <xsl:template match="node">
    <element>
      <xsl:apply-templates />
    </element>
  </xsl:template>
</xsl:stylesheet>

The key is the apply-templates tag to process the tag contents recursively.

Ignacio Vazquez-Abrams
Good answer. You probably would be interested to know about the *identity rule* design pattern -- see my answer.
Dimitre Novatchev
+2  A: 

The way to do this in XSLT is this (using the identity rule and push style):

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

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

when this transformation is applied on the provided XML document:

<root>
  <node>
  </node>
  <node>
    <node>
      <node>
      </node>
    </node>
  </node>
</root>

the wanted, correct result is produced:

<root>
   <element/>
   <element>
      <element>
         <element/>
      </element>
   </element>
</root>

Do note:

  1. The use of the identity rule and its overriding for only a specific element -- this is the most fundamental and powerful XSLT design pattern.

  2. How by using 1. above we achieve ellegant and pure "push style" transformation.

Dimitre Novatchev