Rick
Rick

Reputation: 591

Translating month names into number using only XSL version 1.0

I'm pulling in a custom XML feed from a client's server. I have no control over this XML format. In order to restructure the XML structure I'm using XSLT by running wget and xsltproc to apply a custom style sheet under RHEL 5. Things are working just fine until when we need to do a bit of date conversions.

The feed coming is as such...

...
<event>
   <date>October 3, 2013</date>
   <time>2:00 PM - 4:00 PM</time>
   <moar_xml_here/>
</event>
...

However I need a distinct <startDateTime> and <endDateTime>.

I'm currently converting the date portion in a template as follows. I'm looking over this code and wondering if there is a better way.

<xsl:template match="date">
    <!-- year first -->
    <xsl:value-of select="normalize-space(substring-after(., ','))"/>

    <!-- month  -->
    <xsl:choose>
        <xsl:when test="contains(., 'January')">
            <xsl:value-of select="-01"/>
        </xsl:when>
        <xsl:when test="contains(., 'February')">
            <xsl:value-of select="-02"/>
        </xsl:when>
        <xsl:when test="contains(., 'March')">
            <xsl:value-of select="-03"/>
        </xsl:when>
        <xsl:when test="contains(., 'April')">
            <xsl:value-of select="-04"/>
        </xsl:when>
        <xsl:when test="contains(., 'May')">
            <xsl:value-of select="-05"/>
        </xsl:when>
        <xsl:when test="contains(., 'June')">
            <xsl:value-of select="-06"/>
        </xsl:when>
        <xsl:when test="contains(., 'July')">
            <xsl:value-of select="-07"/>
        </xsl:when>
        <xsl:when test="contains(., 'August')">
            <xsl:value-of select="-08"/>
        </xsl:when>
        <xsl:when test="contains(., 'September')">
            <xsl:value-of select="-09"/>
        </xsl:when>
        <xsl:when test="contains(., 'October')">
            <xsl:value-of select="-10"/>
        </xsl:when>
        <xsl:when test="contains(., 'November')">
            <xsl:value-of select="-11"/>
        </xsl:when>
        <xsl:when test="contains(., 'December')">
            <xsl:value-of select="-12"/>
        </xsl:when>
    </xsl:choose>

    <!-- Get everything before the comma, find the position of the space, and return the remaining value (day as date) -->
    <xsl:variable name="working_to_day" select="normalize-space(substring-before(. , ','))"/>

    <xsl:variable name="space_pos" select="string-length(normalize-space(substring-before(. , ' ')))+1"/>

    <xsl:value-of select="string('-')"/>
    <xsl:value-of select="normalize-space(translate(substring($working_to_day, $space_pos), ' ', '0'))"/>
</xsl:template>

Upvotes: 2

Views: 2845

Answers (1)

David Carlisle
David Carlisle

Reputation: 5652

I suspect you want two digit values, but note

<xsl:value-of select="-08"/>

is same as

<xsl:value-of select="-8"/>

and makes -8

I'd probably use substring-before as in:

$ saxon date.xml date.xsl

original:
 -1

new:
  01


original:
 -10

new:
  10

<x>

<date>January</date>

<date>October</date>

</x>

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


<xsl:template match="date">
original:
 <xsl:choose>
  <xsl:when test="contains(., 'January')">
   <xsl:value-of select="-01"/>
  </xsl:when>
  <xsl:when test="contains(., 'February')">
   <xsl:value-of select="-02"/>
  </xsl:when>
  <xsl:when test="contains(., 'March')">
   <xsl:value-of select="-03"/>
  </xsl:when>
  <xsl:when test="contains(., 'April')">
   <xsl:value-of select="-04"/>
  </xsl:when>
  <xsl:when test="contains(., 'May')">
   <xsl:value-of select="-05"/>
  </xsl:when>
  <xsl:when test="contains(., 'June')">
   <xsl:value-of select="-06"/>
  </xsl:when>
  <xsl:when test="contains(., 'July')">
   <xsl:value-of select="-07"/>
  </xsl:when>
  <xsl:when test="contains(., 'August')">
   <xsl:value-of select="-08"/>
  </xsl:when>
  <xsl:when test="contains(., 'September')">
   <xsl:value-of select="-09"/>
  </xsl:when>
  <xsl:when test="contains(., 'October')">
   <xsl:value-of select="-10"/>
  </xsl:when>
  <xsl:when test="contains(., 'November')">
   <xsl:value-of select="-11"/>
  </xsl:when>
  <xsl:when test="contains(., 'December')">
   <xsl:value-of select="-12"/>
  </xsl:when>
 </xsl:choose>

new:

  <xsl:value-of select="format-number(
                        string-length(substring-before(
     'JanFebMarAprMayJunJulAugSepOctNovDec',
         substring(.,1,3))) div 3 + 1,'00')"/>
</xsl:template>

</xsl:stylesheet>

Upvotes: 2

Related Questions