Wednesday, March 24, 2010

Sorting any XML

I wrote this because I deal with a tool that treats XML as unsorted data. At the same time, it generates an XSD schema that enforces order. So, to solve the problem, I wrote a transform to take XML and alphabetize it by element name. This will work for any XML without namespaces, and will probably work for XML with namespaces by putting a declaration at the top of the transform.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>

<xsl:template match="/">
<xsl:apply-templates select="*" mode="Sorting">
<xsl:sort select="local-name()" />
</xsl:apply-templates>
</xsl:template>

<xsl:template match="*" mode="Sorting">
<xsl:copy>
<xsl:choose>
<xsl:when test="./*">
<xsl:apply-templates select="@*" mode="AttSorting" />
<xsl:apply-templates select="./*" mode="Sorting">
<xsl:sort select="local-name()" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="@*" mode="AttSorting" />
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>

<xsl:template match="@*" mode="AttSorting">
<xsl:copy>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>