Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting Dates from Names to Numbers in XSLT

Tags:

date

xml

xslt

I am trying to convert a date in xml that is in the format 11-APR-16, I would like to parse the date and convert it in 2016-04-11 or yyyy-mm-dd

I currently am using the Xslt code to convert the date:

<xsl:variable name="Date" select="//MEDIAITEMS_ROW/CREATED_DATE"/>
<xsl:variable name="Day" select="substring($Date,1,2)" />
<xsl:variable name="month" select="substring($Date,4,3)" />
<xsl:variable name="Year" select="substring($Date,8,2)" />
<xsl:template name="get-month-abbreviation">
        <xsl:choose>
            <xsl:when test="$month = JAN">01</xsl:when>
            <xsl:when test="$month = FEB">02</xsl:when>
            <xsl:when test="$month = MAR">03</xsl:when>
            <xsl:when test="$month = APR">04</xsl:when>
            <xsl:when test="$month = MAY">05</xsl:when>
            <xsl:when test="$month = JUN">06</xsl:when>
            <xsl:when test="$month = JUL">07</xsl:when>
            <xsl:when test="$month = AUG">08</xsl:when>
            <xsl:when test="$month = SEP">09</xsl:when>
            <xsl:when test="$month = OCT">10</xsl:when>
            <xsl:when test="$month = NOV">11</xsl:when>
            <xsl:when test="$month = DEC">12</xsl:when>
            <xsl:otherwise>error: <xsl:value-of select="$month"/></xsl:otherwise>
        </xsl:choose>

</xsl:template>

However I am still returning the value APR, how should I go about converting the date from letters to number values

like image 391
hguza Avatar asked Mar 12 '23 05:03

hguza


2 Answers

Because you like to compare your variable with an string
change your xsl:when from e.g.:

<xsl:when test="$month = JAN">01</xsl:when>

to:

<xsl:when test="$month = 'JAN'">01</xsl:when>

test="$month = JAN"compares the variable $month with an element JAN in current node.

Update add working example for ARP (only)

<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" encoding="UTF-8"/>

  <xsl:variable name="Date" select="'11-APR-16'"/>
  <xsl:variable name="Day" select="substring($Date,1,2)" />
  <xsl:variable name="month" select="substring($Date,4,3)" />
  <xsl:variable name="Year" select="substring($Date,8,2)" />
  <xsl:template name="get-month-abbreviation">
    <xsl:choose>
         <xsl:when test="$month = 'APR'">04</xsl:when>
        <xsl:otherwise>error: <xsl:value-of select="$month"/></xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="/">
      <xsl:call-template name="get-month-abbreviation" />
  </xsl:template>

</xsl:styles
like image 118
hr_117 Avatar answered Mar 21 '23 05:03

hr_117


Everyone seems to have been assuming that you are using XSLT 1.0, although you don't state this as a constraint, but it's worth knowing that there are lots of things in XSLT 2.0 that make this problem easier.

First and most obvious, you can use regular expressions:

<xsl:analyze-string select="$date" regex="([0-9]{2})\-([A-Z]{3})\-([0-9]{4})">
  <xsl:matching-substring>
    <xsl:value-of select="regex-group(3), f:month-num(regex-group(2)), regex-group(1)" separator="-"/>
  </xsl:matching-substring>
</xsl:analyze-string>

Secondly, you can use functions rather than templates:

<xsl:variable name="months" as="xs:string*" select="'JAN', 'FEB', 'MAR', ..."/>
<xsl:function name="f:month-num" as="xs:string">
  <xsl:param name="month-name" as="xs:string"/>
  <xsl:sequence select="format-number(index-of($months, $month-name), '00')"/>
</xsl:function>

One of the benefits of using functions is that the context doesn't leak into the function. So writing APR rather than 'APR' will give you an error message rather than trying to find a child element named APR. Another benefit is those "as" attributes - data can be type-checked on its way into and out of the function, and this tends to give you earlier and better error messages when you mess up.

like image 42
Michael Kay Avatar answered Mar 21 '23 05:03

Michael Kay