I'm trying to transform a datetime to a date format yyyy-MM-dd, because I'm using the xsd.exe tool the xs:date datatypes are automatically changed into a datetime datatype, because there is no type in the .NET Framework that matches the type xs:date completely.
But I can't get it to work
<articles>
<article>
<articleid>48992</articleid>
<deliverydateasked>2009-01-29T00:00:00+01:00</deliverydateasked>
</article>
<article>
<articleid>48993</articleid>
<deliverydateasked>2009-01-30T00:00:00+01:00</deliverydateasked>
</article>
</articles>
trying to convert the xml to
<articles>
<article>
<articleid>48992</articleid>
<deliverydateasked>2009-01-29</deliverydateasked>
</article>
<article>
<articleid>48993</articleid>
<deliverydateasked>2009-01-30</deliverydateasked>
</article>
</articles>
currently I'm using this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<articles>
<xsl:apply-templates select="article">
</xsl:apply-templates>
</articles>
</xsl:template>
<xsl:template name="FormatDate">
<xsl:param name="DateTime" />
<xsl:variable name="date">
<xsl:value-of select="substring-before($DateTime,'T')" />
</xsl:variable>
<xsl:if test="string-length($date) != 10">
<xsl:value-of select="$DateTime"/>
</xsl:if>
<xsl:if test="string-length($date) = 10">
<xsl:value-of select="$date"/>
</xsl:if>
</xsl:template>
<xsl:template match="article">
<xsl:call-template name="FormatDate">
<xsl:with-param name="DateTime" select="deliverydateasked"/>
</xsl:call-template>
</xsl:template>
Does anyone know a good xslt transformation.
Thanks in advance
The output result of my code is
<articles />
Frankly, this looks about right to me - sometimes a simple substring is good enough.
However, if you're in .NET land and you're really needing extra functionality .NET has XSLT Extension Objects
edit: oic, you've got a basic apply-templates conceptual problem. Try this (note the copy and the root template match):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="*">
<xsl:copy><xsl:apply-templates /></xsl:copy>
</xsl:template>
<xsl:template match="deliverydateasked">
<xsl:copy>
<xsl:call-template name="FormatDate">
<xsl:with-param name="DateTime" select="."/>
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="FormatDate">
<xsl:param name="DateTime" />
<xsl:variable name="date">
<xsl:value-of select="substring-before($DateTime,'T')" />
</xsl:variable>
<xsl:if test="string-length($date) != 10">
<xsl:value-of select="$DateTime"/>
</xsl:if>
<xsl:if test="string-length($date) = 10">
<xsl:value-of select="$date"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
templates is a hard concept to learn, you might be better off starting with the more straightforward for-each
, and/or it seems you could do with some XSLT tutorials/books.
Formatting will get a lot easier in XPath 2.0, which Microsoft has currently refused to support for the last 8 years. Since the formatting issue is really only persistent for XSLT in .Net I like to use a custom function, which is cleaner & easier:
XSLT With Formatting Function:
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="http://www.tempuri.org/User">
<msxsl:script implements-prefix="user" language="C#">
<![CDATA[
public string FormatCurrency(string amount)
{
return decimal.Parse(amount).ToString("C0");
}
public string FormatDate(string dateValue)
{
return DateTime.Parse(dateValue).ToString("MM/dd/yyyy hh:mm");
}
]]>
</msxsl:script>
Usage:
<xsl:value-of select="user:FormatDate(@transactionDate)"/>
<xsl:value-of select="user:FormatCurrency(@amount)"/>
When you execute your XSLT in .Net make sure to tell it that it's trusted (so that the msxsl:script block will run.
XslCompiledTransform.Load(reader, XsltSettings.TrustedXslt, null);
Thanks to Stesoc and annakata I figured it out
This is the code I'm now using and it works perfect
<xsl:template match="*">
<xsl:param name="parentElm">
<xsl:value-of select="name(..)" />
</xsl:param>
<xsl:choose>
<xsl:when test="local-name() = 'deliverydateasked'">
<xsl:element name="deliverydateasked">
<xsl:call-template name="FormatDate">
<xsl:with-param name="DateTime" select="."/>
</xsl:call-template>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{local-name()}">
<xsl:copy-of select="@*" />
<xsl:apply-templates select="@* | node()" />
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="FormatDate">
<xsl:param name="DateTime" />
<xsl:variable name="date">
<xsl:value-of select="substring-before($DateTime,'T')" />
</xsl:variable>
<xsl:if test="string-length($date) != 10">
<xsl:value-of select="$DateTime"/>
</xsl:if>
<xsl:if test="string-length($date) = 10">
<xsl:value-of select="$date"/>
</xsl:if>
</xsl:template>