bluegray
bluegray

Reputation: 600

Convert time string in XSLT

How do I convert a time string like

20101115083000 +0200

to

2010-11-15 08:30:00 +0200

using XSLT?

Upvotes: 2

Views: 9088

Answers (3)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243449

Here is a most generic formatDateTime processing. Input and output format are completely configyrable and passed as parameters:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:call-template name="convertDateTime">
   <xsl:with-param name="pDateTime" select="."/>
  </xsl:call-template>
 </xsl:template>

 <xsl:template name="convertDateTime">
  <xsl:param name="pDateTime"/>
  <xsl:param name="pInFormat">
    <year offset="0" length="4"/>
    <month offset="4" length="2"/>
    <day offset="6" length="2"/>
    <hour offset="8" length="2"/>
    <minutes offset="10" length="2"/>
    <seconds offset="12" length="2"/>
    <zone offset="15" length="5"/>
  </xsl:param>

  <xsl:param name="pOutFormat">
   <y/>-<mo/>-<d/> <h/>:<m/>:<s/> <z/>
  </xsl:param>

  <xsl:variable name="vInFormat" select=
   "document('')/*/xsl:template[@name='convertDateTime']
                       /xsl:param[@name='pInFormat']"/>
  <xsl:variable name="vOutFormat" select=
   "document('')/*/xsl:template[@name='convertDateTime']
                       /xsl:param[@name='pOutFormat']"/>
  <xsl:apply-templates select="$vOutFormat/node()"
       mode="_convertDateTime">
    <xsl:with-param name="pDateTime" select="$pDateTime"/>
    <xsl:with-param name="pInFormat" select="$vInFormat"/>
   </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="y" mode="_convertDateTime">
  <xsl:param name="pDateTime"/>
  <xsl:param name="pInFormat"/>

  <xsl:value-of select=
     "substring($pDateTime,
                1+$pInFormat/year/@offset,
                $pInFormat/year/@length)"/>
 </xsl:template>

 <xsl:template match="mo" mode="_convertDateTime">
  <xsl:param name="pDateTime"/>
  <xsl:param name="pInFormat"/>

  <xsl:value-of select=
     "substring($pDateTime,
                1+$pInFormat/month/@offset,
                $pInFormat/month/@length)"/>
 </xsl:template>

 <xsl:template match="d" mode="_convertDateTime">
  <xsl:param name="pDateTime"/>
  <xsl:param name="pInFormat"/>

  <xsl:value-of select=
     "substring($pDateTime,
                1+$pInFormat/day/@offset,
                $pInFormat/day/@length)"/>
 </xsl:template>

 <xsl:template match="h" mode="_convertDateTime">
  <xsl:param name="pDateTime"/>
  <xsl:param name="pInFormat"/>

  <xsl:value-of select=
     "substring($pDateTime,
                1+$pInFormat/hour/@offset,
                $pInFormat/hour/@length)"/>
 </xsl:template>

 <xsl:template match="m" mode="_convertDateTime">
  <xsl:param name="pDateTime"/>
  <xsl:param name="pInFormat"/>

  <xsl:value-of select=
     "substring($pDateTime,
                1+$pInFormat/minutes/@offset,
                $pInFormat/minutes/@length)"/>
 </xsl:template>

 <xsl:template match="s" mode="_convertDateTime">
  <xsl:param name="pDateTime"/>
  <xsl:param name="pInFormat"/>

  <xsl:value-of select=
     "substring($pDateTime,
                1+$pInFormat/seconds/@offset,
                $pInFormat/seconds/@length)"/>
 </xsl:template>

 <xsl:template match="z" mode="_convertDateTime">
  <xsl:param name="pDateTime"/>
  <xsl:param name="pInFormat"/>

  <xsl:value-of select=
     "substring($pDateTime,
                1+$pInFormat/zone/@offset,
                $pInFormat/zone/@length)"/>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied to the following XML document:

<dateTime>20101115083000 +0200</dateTime>

the wanted, correct result is produced:

   2010-11-15 08:30:00 +0200

Upvotes: 2

LarsH
LarsH

Reputation: 27994

If you have XSLT 2.0, you can use date parsing and formatting functions.

If you have XSLT 1.0, but can use EXSLT, it provides similar functions.

These would be less transparent to use than @Peter's explicit code, but maybe more robust if your input format can vary.

Upvotes: 2

Peter
Peter

Reputation: 14108

We use templates:

<xsl:template name="format-date-time">
    <xsl:param name="date" select="'%Y-%m-%dT%H:%M:%S%z'"/>
    <xsl:value-of select="substring($date, 9, 2)"/>
    <xsl:text>/</xsl:text>
    <xsl:value-of select="substring($date, 6, 2)"/>
    <xsl:text>/</xsl:text>
    <xsl:value-of select="substring($date, 1, 4)"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="substring($date, 12, 2)"/>
    <xsl:text>:</xsl:text>
    <xsl:value-of select="substring($date, 15, 2)"/>
    <xsl:text>:</xsl:text>
    <xsl:value-of select="substring($date, 18, 2)"/>
</xsl:template>

We call these templates like this:

<xsl:call-template name="format-date-time">
    <xsl:with-param name="date" select="./Startdate"/>
</xsl:call-template>

./Startdate is an XML date, but with the substring technique, I think you could solve your problem too.

Upvotes: 10

Related Questions