Monday, 18 February 2008

Re-arrange the order of elements in an XML document

Often people need to reorganize their XML for further processing, and this is a great opportunity to clarify available techniques.

You can use xsl:copy and/or copy-of, although I doubt your goal in practice will always be as simple as that.


Input xml:
<ROOT>
<A1>A</A1>
<B1>B</B1>
<C1>C</C1>
<D1>D</D1>
</ROOT>

Required output xml:
<ROOT>
<A1>A</A1>
<D1>D</D1>
<B1>B</B1>
<C1>C</C1>
</ROOT>


If you need to restructure the children of the root element for example, and you're confident about the simplicity of the XML you're trying to restructure, then you'd do something like this:
<xsl:template match="/ROOT">
<xsl:copy>
<xsl:copy-of select="A1"/>
<xsl:copy-of select="D1"/>
<xsl:copy-of select="B1"/>
<xsl:copy-of select="C1"/>
</xsl:copy>
</xsl:template>

The above code will output what we've planned for. Now, if you have a much larger document, and what you're really after is moving some of the nodes around while maintaining an abstract hierarchy, you could use the technique in example code below.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="*">
<xsl:apply-templates select="self::*" mode="copy"/>
</xsl:template>

<xsl:template match="A1">
<xsl:apply-templates select="self::*" mode="copy"/>
<xsl:apply-templates select="../D1" mode="copy"/>
</xsl:template>


<xsl:template match="B1">
<xsl:apply-templates select="self::*" mode="copy"/>
<xsl:apply-templates select="../C1" mode="copy"/>
</xsl:template>

<xsl:template match="D1"/>
<xsl:template match="C1"/>

<xsl:template match="*" mode="copy">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

<xsl:template match="text()">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>


In this case you are copying an abstract document structure and repositioning some of the elements in strategic places.

3 comments:

dave said...

Just what I needed at a time of crisis - thanks mate!!!

Anonymous said...

hi, good site very much appreciatted

Miguel de Melo said...

glad it was of use to you :)