I have the following XML document:
<?xml version="1.0" encoding="UTF-8"?>
<objects>
    <object>Clutch</object>
    <object>Gearbox</object>
    <object>Cylinder head</object>
    <object>Starter</object>
    <object>Airbox</object>
    <object>Inlet manifold</object>
</objects>
And the following XSLT document:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="objects">
        <parts>
            <xsl:apply-templates>
                <xsl:sort select="object"/>
            </xsl:apply-templates>
        </parts>
    </xsl:template>
    <xsl:template match="object">
        <part>
            <xsl:apply-templates/>
        </part>
    </xsl:template>
</xsl:stylesheet>
When applied I am getting the following output as expected, but it is not being sorted:
<?xml version="1.0" encoding="UTF-8"?>
<parts>
    <part>Clutch</part>
    <part>Gearbox</part>
    <part>Cylinder head</part>
    <part>Starter</part>
    <part>Airbox</part>
    <part>Inlet manifold</part>
</parts>
Why is the <xsl:sort select="object"/> not being applied ?
The reason is here:
<parts> <xsl:apply-templates> <xsl:sort select="object"/> </xsl:apply-templates> </parts>
This applies templates to the children (object) of the current node (objects) and sorts them by the string value of their first object child.
However in the provided XML document an object doesn't have any object children -- so they all have the same sort-key -- the empty string -- and their original order isn't changed by the sort operation.
Solution:
        <parts>
            <xsl:apply-templates>
                <xsl:sort select="."/>
            </xsl:apply-templates>
        </parts>
The complete transformation becomes:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:template match="objects">
    <parts>
     <xsl:apply-templates>
        <xsl:sort select="."/>
     </xsl:apply-templates>
    </parts>
 </xsl:template>
 <xsl:template match="object">
  <part>
     <xsl:apply-templates/>
  </part>
 </xsl:template>
</xsl:stylesheet>
and when it is applied to the provided XML document:
<objects>
    <object>Clutch</object>
    <object>Gearbox</object>
    <object>Cylinder head</object>
    <object>Starter</object>
    <object>Airbox</object>
    <object>Inlet manifold</object>
</objects>
the wanted, correct result is produced:
<parts>
   <part>Airbox</part>
   <part>Clutch</part>
   <part>Cylinder head</part>
   <part>Gearbox</part>
   <part>Inlet manifold</part>
   <part>Starter</part>
</parts>
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With