Sorting Data by Numeric Value

MSXML 5.0 SDK

Microsoft XML Core Services (MSXML) 5.0 for Microsoft Office - XSLT Developer's Guide

Sorting Data by Numeric Value

When sorting data, MSXML can treat the sort key as text, or as a number. You can specify how the sort key should be treated in either of the following ways.

<xsl:sort select="name" data-type="text"/>

or

<xsl:sort select="quantity" data-type="number"/>

If you do not specify a data type, MSXML treats the sort key as text. If you want the sort key to be treated as a number, you must to set the data-type attribute to "number", explicitly. The reason for specifying a data type other than the default "text" is that non-text values might sort improperly if treated as text. For example, the following are sorted correctly as text, but incorrectly as numbers:

1004
109
12

The default text sort order compares the values by looking at each character in each value from left to right: 100 is less than 109, so a string beginning with 100 sorts ahead of one beginning with 109. And the leading 10 in both 1004 and 109 sorts ahead of the 12. However, we almost certainly want these values to be sorted as numbers:

12
109
1004

In Sorting by Two Columns, the sorted table based on prodsort.xml displays products sorted first by categories and then, within each category, by product name. Notice, though, that there are two versions of the Wooden Rings Workbench product, and that the corresponding two rows of the table are still in document order.

The next example adds a third sort level to the existing two.

Example

When you compare the formatted output of the following example to the previous version of the table, note that Wooden Rings Workbench versions 4.0 and 4.5 have switched places.

The version number can be used as a sort key, even though it does not display as a separate column. In fact, any document content can be used as a sort key, even if it is not displayed at all.

XML File (prodsort.xml)

Use prodsort.xml, in Sample XML Data File for XSLT Sorting. Change the href attribute to reference prodsort3.xsl.

XSLT File (prodsort3.xsl)

This is the final version of this series of XSLT files.

<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
   <HTML>
      <HEAD>
         <TITLE>Wooden Rings and More!</TITLE>
         <STYLE type="text/css">
            th {background-color: silver;
               font-family: Tahoma,Verdana,Arial,sans-serif}
            td {background-color: white;
               font-family: Tahoma,Verdana,Arial,sans-serif}
         </STYLE>
      </HEAD>
      <BODY>
         <xsl:apply-templates/>
      </BODY>
   </HTML>
</xsl:template>

<xsl:template match="products">
    <TABLE width="75%">
        <tr>
            <th>Category</th>
            <th>Prod ID</th>
            <th>Name/Version</th>
            <th>Description</th>
            <th>Price/Units</th>
        </tr>
        <xsl:apply-templates>
            <xsl:sort select="categ"/>
            <xsl:sort select="name"/>
            <xsl:sort select="version" data-type="number"/>
        </xsl:apply-templates>
    </TABLE>
</xsl:template>

<xsl:template match="product">
   <tr>
      <td valign="top"><xsl:value-of select="categ"/></td>
      <td valign="top"><xsl:value-of select="@prodID"/></td>
      <td valign="top"><xsl:value-of select="concat(name, '/', version)"/></td>
      <td valign="top"><xsl:value-of select="descr"/></td>
      <td valign="top" align="center"><xsl:value-of select="concat(price, ' (', price/@curr, ')')"/></td>
   </tr>
</xsl:template>

</xsl:stylesheet>

Formatted Output