Michael
Michael

Reputation: 425

XSLT: how to sort date

I have a question about sort date time.

I found a solution here but this solution is not work for me.

suppose I have a xml. The date order is month, day and year.

<persons>
  <person>
     <name>1</name>
     <birthday>021514</birthday>
  </person>
  <person>
     <name>2</name>
     <birthday>051513</birthday>
  </person>
</persons>

I have a xsl

        <xsl:for-each select="//person">
            <!-- day -->
            <xsl:sort select="substring(birthday, 3, 2)" order="descending" data-type="number"/>
            <!-- month -->
            <xsl:sort select="substring(birthday, 1, 2)" order="descending" data-type="number"/>
            <!-- year -->
            <xsl:sort select="substring(birthday, 5, 2)" order="descending" data-type="number"/>
            <xsl:value-of select="birthday"/>
        </xsl:for-each>

I want the date sort in decreasing order.

I get result

051513
021514

but the actual result I want is

021514
051513    

Only the first sort is working. The rest of sorts are not working. What's wrong with this code? Any help would be appreciated.

Upvotes: 0

Views: 4345

Answers (2)

Jaroslav Kubacek
Jaroslav Kubacek

Reputation: 1447

Just change order of sorting conditions.
You should start by Year, Month and Day.

<xsl:for-each select="//person">
  <!-- year -->
  <xsl:sort select="substring(birthday, 5, 2)" order="descending" data-type="number"/>
  <!-- month -->
  <xsl:sort select="substring(birthday, 1, 2)" order="descending" data-type="number"/>
  <!-- day -->
  <xsl:sort select="substring(birthday, 3, 2)" order="descending" data-type="number"/>
  <xsl:value-of select="birthday"/>
</xsl:for-each>

Upvotes: 2

Michael Kay
Michael Kay

Reputation: 163342

If you have XML using MMDDYY as the date format then it is badly designed XML, and the best thing to do with badly designed XML is to clean it up in a preprocessing phase before you do anything else. Write a stylesheet whose only purpose is to clean the XML up into something better, and then think about the transformation tasks as a separate processing phase.

In this case you want to create dates in the ISO form YYYY-MM-DD. I'm not sure what your rule is for inferring the century, but I would write something like the following (needs XSLT 2.0):

<xsl:template match="birthday">
  <xsl:copy>
    <xsl:variable name="year" select="substring(., 5, 2)"/>
    <xsl:variable name="month" select="substring(., 1, 2)"/>
    <xsl:variable name="day" select="substring(., 3, 2)"/>
    <xsl:value-of select="if (number($year) gt 20 then '19' else '20'"/>
    <xsl:value-of select="$year, $month, $day" separator="-"/>
  </xsl:copy>
</xsl:template>

Upvotes: 1

Related Questions