tags:

views:

213

answers:

3

I'm trying to order items based on an attribute value:

<xsl:apply-templates select="Question">
    <xsl:sort order="ascending" select="@Value"></xsl:sort>
</xsl:apply-templates>

This does order them, but I could have values like 1,2,3, ... 10, 11, ... 20 and it will order them 1,10,11, ... 2,20... 3. etc.
I could also have values like 1.A, 1.B, 2.A, 2.B etc.

How can I order these values to take into account the numeric content and the alphabetic, in that priority?

+2  A: 

You can sort in numeric order using the data-type attribute:

<xsl:sort order="ascending" select="@Value" data-type="number"></xsl:sort>

The built-in sort function does not have support for more complex ordering (such as the multipart keys you mention).

Greg Hewgill
A: 

For sorting numbers you can use this:

<xsl:template match="employees">
  <xsl:apply-templates>
    <xsl:sort select="salary" data-type="number"/>
  </xsl:apply-templates>
</xsl:template>

Note that the data-type attribute is used here. For values like values like 1.A, 1.B, 2.A, 2.B you are back to text again and will have to resort to clever stuff that probably resorts to ugly nesting. Do consider the xsl:number element which can be used in interesting ways.

rasx
+5  A: 

If you know that every question has a multi-part number, you could handle them with two <xsl:sort> instructions:

<xsl:apply-templates select="Question">
  <xsl:sort select="substring-before(@Value, '.')" data-type="number" />
  <xsl:sort select="substring-after(@Value, '.')" />
</xsl:apply-templates>

If some of the numbers might have multiple parts and some not, I guess the best thing to do is:

<xsl:apply-templates select="Question">
  <xsl:sort select="substring-before(concat(@Value, '.'), '.')" data-type="number" />
  <xsl:sort select="substring-after(@Value, '.')" />
</xsl:apply-templates>

The extra concat(@Value, '.') adds a '.' to the end of the value so that the substring-before() always gets the number.

JeniT