I'd like to sort one XML file with an XSL transformation.
<root>
   <element>
        <name>A</name>
   </element>
   <element>
        <name>B</name>
   </element>
   <element>
        <name>C</name>
   </element>
</root>
Must be sorted by the following list of names: C, A, B so that the resulting XML is:
 <root>
       <element>
            <name>C</name>
       </element>
       <element>
            <name>A</name>
       </element>
       <element>
            <name>B</name>
       </element>
    </root>
Obviously the list of values to be sort on should be quite dynamic (parameter of the XSLT, another XML file...). Any idea how to do that in the XSLT ?
Thanks, Christophe
This transformation:
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:param name="pSortingValues" select="'C,A,B'"/>
 <xsl:variable name="vSortingValues" select=
  "concat(',', $pSortingValues, ',')"/>
    <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>
    <xsl:template match="/*">
      <xsl:copy>
       <xsl:apply-templates select="@*"/>
       <xsl:apply-templates select="*">
        <xsl:sort data-type="number" select=
        "string-length(substring-before($vSortingValues,concat(',',name,',')))"/>
       </xsl:apply-templates>
      </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<root>
    <element>
        <name>A</name>
    </element>
    <element>
        <name>B</name>
    </element>
    <element>
        <name>C</name>
    </element>
</root>
produces the wanted, correct results:
<root>
   <element>
      <name>C</name>
   </element>
   <element>
      <name>A</name>
   </element>
   <element>
      <name>B</name>
   </element>
</root>
Do note:
The desired sorted values list is the pSortingValues global parameter, which can be provided externally to the transformation.
The identity rule is used to copy all nodes "as-is".
The identity rule is overriden for the top element. The top element is partially copied, its attributes are copied, then templates are applied on all children-elements with an <xsl:sort> child instruction, which specifies the exact sort key to be used -- how in front of the pSortingValues values the name of the element child is.
UPDATE: As noted by @Alejandro, this:
        <xsl:sort data-type="number" select=
        "string-length(substring-before($vSortingValues,concat(',',name,',')))"/>
may be simplified to this:
        <xsl:sort data-type="number" select=
        "substring-before($vSortingValues,concat(',',name,','))"/>
                        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