65.9K
CodeProject is changing. Read more.
Home

Sorting Dates in XSL

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.90/5 (10 votes)

Jun 3, 2003

2 min read

viewsIcon

87345

Sorting dates in XSL

Introduction

This article assumes that the reader has some prior knowledge of XML and XSL. XSL provides infrastructure for sorting on character and numerical values. But nothing is provided for sorting date. This article presents two ways for sorting XML data based on date.

First Way by Numerical Method

Let's say you have an XML data as follows:

<Root>
  <Element StartDate="26 January 2003"/>
  <Element StartDate="28 Feburary 1979"/>
  <Element StartDate="3 November 1989"/>
  <Element StartDate="1 July 2003"/>
  <Element StartDate="26 January 1977"/>
</Root>

(Section a)

You can sort it by having one more attribute for each Element node which will have the following format "yyyymmdd". For example: if the date is 26 January 2003, then the format will be "20030126". 2003 is the year, 01 is the month and finally 26 is the date. So let's have one more attribute called SortDate, so our above XML will look like:

<Root>
  <Element StartDate="26 January 2003" SortDate="20030126"/>
  <Element StartDate="28 Feburary 1979" SortDate="19790228"/>
  <Element StartDate="3 November 1989" SortDate="19891103"/>
  <Element StartDate="1 July 2003" SortDate="20030701"/>
  <Element StartDate="26 January 1977" SortDate="19770126"/>
</Root>

Note: Month name and day which are less than 10 should be denoted by two numeric values, otherwise it will affect the sort order, resulting in wrong results. For example: January should be denoted by "01".

Now sort the XML data with respect to SortDate attribute and sorting using numerical data.

<xsl:sort select="@SortDate" data-type="numeric" order="descending"/>

Second Way by String Method

To explain how this method works, let me first give you code which will be used to sort the above XML data (Section a) by this method.

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <xsl:variable name="vMonthNames" 
    select="'|January|February|March|April|May|June|July|
    August|September|October|November|December'"/>
      <xsl:template match="/">
         <xsl:for-each select="Root/Element">
         <!-- year part -->
         <xsl:sort 
            select="substring-after(substring-after(@Startdate,' '),' ')" 
            data-type="number"/>
         <!-- month part -->
         <xsl:sort 
           select="string-length(substring-before($vMonthNames,
             substring-before(substring-after(@Startdate,' '),' ')))" 
           data-type="number"/>
         <!-- day part -->
         <xsl:sort select="substring-before(@Startdate,' ')" 
           data-type="number"/>
         <xsl:value-of select="@date"/><br/>
         </xsl:for-each>
     </xsl:template>
</xsl:stylesheet>

The idea is extract the year part of the date and sort the date values using year, then extract the month part of the date and find the month string in the variable vMonthNames, you will find the index and that index is used to sort the month. For example, if you find "January", you will get the index as '1' and if you find "March", you will get an index 18. This is how "January" is less than "March". And finally extract the day part from the date and sort on it.

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below. A list of licenses authors might use can be found here.