Rob
Rob

Reputation: 10248

customise xsl:sort - xslt V1

I have xml with the follow node ContractLength and it has 4 possible values:

None, 1 Year, 2 Year, 3 Year

I am wondering if it is possible to sort them in the order they appear above...

<xsl:sort select="ContractLength" order="ascending" data-type="text"/>

Gives me 1 Year, 2 Year, 3 Year, None

<xsl:sort select="ContractLength" order="ascending" data-type="text"/>

Gives me None, 3 Year, 2 Year, 1 Year

but I want None to be treated as 0 resulting in None, 1 Year, 2 Year, 3 Year

I am restricted to using xslt V1.0

The sort xsl currently fits into the code like this:

<xsl:choose>
  <xsl:when test="$sort = 'greenpower'">
      <xsl:apply-templates select="Product">
          <xsl:sort select="GreenPercent" order="descending" data-type="number" />
      </xsl:apply-templates>
  </xsl:when>
  <xsl:when test="$sort = 'estimatedcost'">
      <xsl:apply-templates select="Product">
          <xsl:sort select="EstimatedCost/Maximum" order="ascending" data-type="number" />
      </xsl:apply-templates>
  </xsl:when>
  <xsl:when test="$sort = 'contractterm'">
      <xsl:apply-templates select="Product">
          <xsl:sort select="ContractLength" order="ascending" data-type="text"/>
      </xsl:apply-templates>
  </xsl:when>
</xsl:choose>

Upvotes: 2

Views: 128

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243459

Good question, +1.

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

 <xsl:template match="/*">
     <xsl:copy>
       <xsl:apply-templates select="*">
        <xsl:sort select="number(substring-before(.,' '))"
                  data-type="number"/>
       </xsl:apply-templates>
     </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

when applied on the following XML document (none was provided!!!):

<t>
 <clen>2 year</clen>
 <clen>none</clen>
 <clen>1 year</clen>
 <clen>3 year</clen>
</t>

produces the wanted, correct result:

<t>
   <clen>none</clen>
   <clen>1 year</clen>
   <clen>2 year</clen>
   <clen>3 year</clen>
</t>

Explanation:

number(substring-before('none',' '))

is NaN

and NaN comes before any other number when sorted with data-type="number".

Upvotes: 2

Related Questions