[ACCEPTED]-Format a date in XML via XSLT-xslt

Accepted answer
Score: 70

Here are a couple of 1.0 templates that 3 you can use:-

<xsl:template name="formatDate">
    <xsl:param name="dateTime" />
    <xsl:variable name="date" select="substring-before($dateTime, 'T')" />
    <xsl:variable name="year" select="substring-before($date, '-')" />
    <xsl:variable name="month" select="substring-before(substring-after($date, '-'), '-')" />
    <xsl:variable name="day" select="substring-after(substring-after($date, '-'), '-')" />
    <xsl:value-of select="concat($day, ' ', $month, ' ', $year)" />
</xsl:template>

<xsl:template name="formatTime">
    <xsl:param name="dateTime" />
    <xsl:value-of select="substring-after($dateTime, 'T')" />
</xsl:template>

Call them with:-

    <xsl:call-template name="formatDate">
        <xsl:with-param name="dateTime" select="xpath" />
    </xsl:call-template>

and

    <xsl:call-template name="formatTime">
        <xsl:with-param name="dateTime" select="xpath" />
    </xsl:call-template>

where xpath 2 is the path to an element or attribute that 1 has the standard date time format.

Score: 26

Date formatting is not easy in XSLT 1.0. Probably 19 the most elegant way is to write a short 18 XSLT extension function in C# for date formatting. Here's 17 an example:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:myExtension="urn:myExtension"
                exclude-result-prefixes="msxsl myExtension">
  <xsl:output method="xml" indent="yes"/>

  <msxsl:script implements-prefix="myExtension" language="C#">
    <![CDATA[
      public string FormatDateTime(string xsdDateTime, string format)
      {
          DateTime date = DateTime.Parse(xsdDateTime);
          return date.ToString(format); 
      }

    ]]>
  </msxsl:script>

  <xsl:template match="date">
    <formattedDate>
      <xsl:value-of select="myExtension:FormatDateTime(self::node(), 'd')"/>
    </formattedDate>
  </xsl:template>
</xsl:stylesheet>

With this input document

<?xml version="1.0" encoding="utf-8"?>
<date>2007-11-14T12:01:00</date>

you 16 will get

<?xml version="1.0" encoding="utf-8"?>
<formattedDate>14.11.2007</formattedDate> 

The function formatting the date 15 takes a date value as string and a format 14 as described in DateTime.ToString Method. Using .NET's DateTime 13 struct gives you parsing arbitrary XSD datetime 12 values (including time zone specifiers), timezone 11 calculation and localized output for free.

However, be 10 aware that there is one caveat (http://support.microsoft.com/kb/316775) with msxml script 9 extensions: Each time you load the XSLT 8 an assembly containing the script code is 7 generated dynamically and loaded into memory. Due 6 to the design of the .NET runtime, this 5 assembly cannot be unloaded. That's why 4 you have to make sure that your XSLT is 3 only loaded once (and then cached for further 2 re-use). This is especially important when 1 running inside IIS.

Score: 9

John Workman discusses this issue at length 7 and gives several solutions in this discussion[1] on 6 his blog. Basically, parse the individual 5 date components and recombine in whatever 4 order you wish. For your case, a pure XSLT 3 1.0+ version would be:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="date">
<!-- converts FROM <date>2001-12-31T12:00:00</date> TO some new format (DEFINED below) -->
<xsl:template name="FormatDate">
<xsl:param name="DateTime" />

<xsl:variable name="year" select="substring($DateTime,1,4)" />
<xsl:variable name="month-temp" select="substring-after($DateTime,'-')" />
<xsl:variable name="month" select="substring-before($month-temp,'-')" />
<xsl:variable name="day-temp" select="substring-after($month-temp,'-')" />
<xsl:variable name="day" select="substring($day-temp,1,2)" />
<xsl:variable name="time" select="substring-after($DateTime,'T')" />
<xsl:variable name="hh" select="substring($time,1,2)" />
<xsl:variable name="mm" select="substring($time,4,2)" />
<xsl:variable name="ss" select="substring($time,7,2)" />

<!-- EUROPEAN FORMAT -->
<xsl:value-of select="$day"/>
<xsl:value-of select="'.'"/> <!--18.-->
<xsl:value-of select="$month"/>
<xsl:value-of select="'.'"/> <!--18.03.-->
<xsl:value-of select="$year"/>
<xsl:value-of select="' '"/> <!--18.03.1976 -->
<xsl:value-of select="$hh"/>
<xsl:value-of select="':'"/> <!--18.03.1976 13: -->
<xsl:value-of select="$mm"/>
<xsl:value-of select="':'"/> <!--18.03.1976 13:24 -->
<xsl:value-of select="$ss"/> <!--18.03.1976 13:24:55 -->
<!-- END: EUROPEAN FORMAT -->

</xsl:template>

Another format (REPLACEs 2 the EUROPEAN FORMAT section):

<!-- Long DATE FORMAT -->
<xsl:choose>
<xsl:when test="$month = '1' or $month= '01'">January</xsl:when>
<xsl:when test="$month = '2' or $month= '02'">February</xsl:when>
<xsl:when test="$month= '3' or $month= '03'">March</xsl:when>
<xsl:when test="$month= '4' or $month= '04'">April</xsl:when>
<xsl:when test="$month= '5' or $month= '05'">May</xsl:when>
<xsl:when test="$month= '6' or $month= '06'">June</xsl:when>
<xsl:when test="$month= '7' or $month= '07'">July</xsl:when>
<xsl:when test="$month= '8' or $month= '08'">August</xsl:when>
<xsl:when test="$month= '9' or $month= '09'">September</xsl:when>
<xsl:when test="$month= '10'">October</xsl:when>
<xsl:when test="$month= '11'">November</xsl:when>
<xsl:when test="$month= '12'">December</xsl:when>
</xsl:choose> 
<xsl:value-of select="' '"/> <!--January -->
<xsl:value-of select="$day"/> <!--January 12 -->
<xsl:value-of select="','"/> <!--January 12,-->
<xsl:value-of select="' '"/> <!--January 12, -->
<xsl:value-of select="$year"/> <!--January 12, 2001-->
<!-- END: Long DATE FORMAT -->

You can recombine 1 the elements in any way you choose.

[1] http://geekswithblogs.net/workdog/archive/2007/02/08/105858.aspx @@ http://archive.is/4Hjep

Score: 5

Apologies for commenting on this old thread 19 but for others finding it like me you could 18 also use javascript if you are using an 17 MS transformer:

Declare the "msxsl" namespace:

xmlns:msxsl="urn:schemas-microsoft-com:xslt" 

Declare 16 a namespace for your script:

xmlns:js="urn:custom-javascript" 

(Optional) Omit 15 the prefixes from the output:

exclude-result-prefixes="msxsl js" 

So you end 14 up with an xsl declaration like this:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  xmlns:js="urn:custom-javascript"
  exclude-result-prefixes="msxsl js">

Write 13 the JavaScript in the msxsl:script element:

<msxsl:script language="JavaScript" implements-prefix="js"> 
<![CDATA[ 
function javascriptFunction(dateValue){
  var date = new Date(dateValue);
  if(!isNaN(date)) return date.toLocaleString();
  return dateValue;
}
]]>
</msxsl:script>

Call 12 your JavaScript function (using the XPath 11 syntax '.' denoting 'this node'):

<xsl:value-of select="js:javascriptFunction(string(.))"/>

NB: As 10 of writing there doesn't seem to be an (xsl) way 9 to include external js files (eg. jquery 8 library). This could be done by parsing 7 the xsl file server side before the transformation 6 and adding the js file contents as a string 5 into a CDATA section. I started to go down 4 this route myself but concluded that if 3 you need this level of functionality it 2 might be better placed in a different part 1 of the pipeline.

source: http://dev.ektron.com/kb_article.aspx?id=482
ref: http://www.ibm.com/developerworks/xml/library/x-tipxsltjs/index.html

Score: 3

correction to roy's post: the day from the 2 function will always get the month value. Use 1 the following:

<xsl:variable name="year" select="substring($dateTime,1,4)" />
<xsl:variable name="month-temp" select="substring-after($dateTime,'-')" />
<xsl:variable name="month" select="substring-before($month-temp,'-')" />
<xsl:variable name="day-temp" select="substring-after($month-temp,'-')" />
<xsl:variable name="day" select="substring($day-temp,1,2)" />
<xsl:variable name="time" select="substring-after($dateTime,'T')" />
<xsl:variable name="hh" select="substring($time,1,2)" />
<xsl:variable name="mm" select="substring($time,4,2)" />
<xsl:variable name="ss" select="substring($time,7,2)" />

<xsl:value-of select="concat($month,'/',$day,'/',$year,' ',$hh,':',$mm,':',$ss)" />

Score: 3

Thanks, this post helped a lot.

I was transforming 3 an RSS feed which uses the following date 2 format: Mon, 04 Apr 2011 23:18:00 -0700. Here is the named template I used 1 to parse it.

<!--Parse date format: Mon, 04 Apr 2011 23:18:00 -0700-->
<xsl:template name="formatDate">

    <xsl:param name="dateIn" />

    <xsl:variable name="day" select="substring($dateIn, 0, 3)" />
    <xsl:variable name="date" select="substring($dateIn, 6, 2)" />
    <xsl:variable name="month" select="substring($dateIn, 9, 3)" />
    <xsl:variable name="year" select="substring($dateIn, 13, 4)" />

    <xsl:variable name="hour" select="substring($dateIn, 18, 2)" />
    <xsl:variable name="min" select="substring($dateIn, 21, 2)" />
    <xsl:variable name="sec" select="substring($dateIn, 24, 2)" />

    <xsl:value-of select="concat($date, ' ', $month, ' ', $year, ' ', $hour, ':', $min, ':', $sec)" />

</xsl:template>
Score: 1
<xsl:template match="date">
     <xsl:copy>
         <xsl:call-template name="formatdate">
             <xsl:with-param name="DateTimeStr" select="."/>
        </xsl:call-template>
     </xsl:copy>
  </xsl:template>

  <xsl:template name="formatdate">
     <xsl:param name="DateTimeStr" />

     <!-- input format xslt datetime string -->
     <!-- output format mm/dd/yyyy -->

     <xsl:variable name="datestr">
         <xsl:value-of select="substring-before($DateTimeStr,'T')" />
     </xsl:variable>

     <xsl:variable name="mm">
         <xsl:value-of select="substring($datestr,6,2)" />
     </xsl:variable>

     <xsl:variable name="dd">
        <xsl:value-of select="substring($datestr,9,2)" />
     </xsl:variable>

     <xsl:variable name="yyyy">
        <xsl:value-of select="substring($datestr,1,4)" />
     </xsl:variable>

     <xsl:value-of select="concat($mm,'/', $dd, '/', $yyyy)" />
  </xsl:template>

This worked for me. You can check other 1 options at :

https://blog.fpmurphy.com/2008/05/xslt-datetime-formatting.html

Score: 0

With XSLT2 lib, you can

  • parse the text : get the dateTime format with xs:dateTime(text())
  • format the dateTime format with the XSLT 2 function : format-dateTime [*]

[*] https://www.w3.org/TR/xslt20/#function-format-dateTime

With your XML 1 sample

<Date>2007-11-14T12:01:00</Date>

The XSL snippet

<p>My date : <xsl:value-of select="format-dateTime(xs:dateTime(text()), '[Y0001]-[M01]-[D01] [H01]:[m]:[s]')"/></p>

The result is

<p>My date : 2007-11-14 12:01:00</p>

More Related questions