XSLT convert date format
Solution 1
Your question is a little vague. It needs some sample input and expected output. But any way, here is an answer to best guess at what you want.
Given this input:
<?xml version="1.0"?>
<dates>
<date>11/12/2012</date>
<date>3/4/2011</date>
</dates>
... transformed by this style-sheet ...
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="dates">
<xsl:copy>
<xsl:apply-templates select="*" />
</xsl:copy>
</xsl:template>
<xsl:template match="date">
<xsl:copy>
<xsl:value-of select="
concat(
substring-after(substring-after(.,'/'),'/') , '-',
format-number( number( substring-before(.,'/')), '00') , '-',
format-number( substring-before(substring-after(.,'/'),'/'), '00')
)
" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
... will produce this desired output ...
<dates>
<date>2012-11-12</date>
<date>2011-03-04</date>
</dates>
Please tick the answer if it is correct. I verified this solution on http://www.purplegene.com/static/transform.html
Solution 2
My XSLT shown below should work. It does not use hard-coded lengths or indexes, but instead splits the date string on '/' to work out where the day, month and year components are.
XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<!-- match the date and invoke formatDate to format it -->
<xsl:template match="date">
<xsl:element name="date">
<xsl:call-template name="formatDate">
<xsl:with-param name="dateParam" select="." />
</xsl:call-template>
</xsl:element>
</xsl:template>
<xsl:template name="formatDate">
<xsl:param name="dateParam" />
<!-- input format mm/dd/yyyy or m/d/yyyy -->
<!-- output format yyyy-mm-dd -->
<!-- parse out the day, month and year -->
<xsl:variable name="month" select="substring-before($dateParam,'/')" />
<xsl:variable name="day" select="substring-before(substring-after($dateParam,'/'),'/')" />
<xsl:variable name="year" select="substring-after(substring-after($dateParam,'/'),'/')" />
<!-- now print them out. Pad with 0 where necessary. -->
<xsl:value-of select="$year" />
<xsl:value-of select="'-'" />
<xsl:if test="string-length($month) = 1">
<xsl:value-of select="'0'" />
</xsl:if>
<xsl:value-of select="$month" />
<xsl:value-of select="'-'" />
<xsl:if test="string-length($day) = 1">
<xsl:value-of select="'0'" />
</xsl:if>
<xsl:value-of select="$day" />
</xsl:template>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Input:
<input>
<date>04/30/2012</date>
<date>4/1/2012</date>
</input>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<input>
<date>2012-04-30</date>
<date>2012-04-01</date>
</input>
Demo: http://www.xsltcake.com/slices/kBveVQ
TimWagaman
Updated on July 17, 2022Comments
-
TimWagaman almost 2 years
I'm having an issue where I'm getting an XML file, and from the samples that I get the format of date that I'm getting is
mm/dd/yyyy
and sometimes it ism/d/yyyy
. My task is to convert this to another XML file where the schema only acceptsyyyy-mm-dd
. I'm limited to using XSLT 1.0/XPATH 1.0. How can I do this? -
Sean B. Durkin almost 12 yearsDogbane's solution is pretty similiar to mine, but he beat me to the punch. Still, I think my solution is briefer and reads better. McLaren's solution won't work on dates like 1/12/2012 which has string length 9.
-
Michael Kay almost 12 yearsPlease don't use
<xsl:variable><xsl:value-of select="xxx"/></xsl:variable>
when you could use<xsl:variable select="xxx"/>
. It's verbose and inefficient! -
Mikro Koder about 7 yearsHello team! See below , exposing format-dateTime: stackoverflow.com/a/16892467/2816548