16

I have a node in my XML file containing the following:

<Apple>2011-12-01T16:33:33Z</Apple>

I wish to take this line and replace it with the current date and time using the same format as shown above.

YYYY-MM-DDTHH:MM:SSZ

The node is within a namespace declared as 'x'

Kirill Polishchuk
  • 54,804
  • 11
  • 122
  • 125
Mike
  • 618
  • 2
  • 8
  • 27
  • possible duplicate: http://stackoverflow.com/questions/500915/format-a-date-in-xml-via-xslt – Siva Charan Feb 22 '12 at 12:02
  • @SivaCharan, no its not, he is seeking CURRENT DATE-TIME rather than format. – Rookie Programmer Aravind Feb 22 '12 at 12:09
  • See http://stackoverflow.com/questions/5475699/cannot-use-the-current-datetime-function-in-xslt and http://stackoverflow.com/questions/1575111/can-an-xslt-insert-the-current-date. If you can't use XSLT 2.0, use a script function – StuartLC Feb 22 '12 at 12:12

3 Answers3

15

Playing with DateTime is not possible with XSLT 1.0 alone .. In a similar situations I took help of scripting .. (C#)

Sample XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <Apple>2011-12-01T16:33:33Z</Apple>
</root>

Sample XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns:cs="urn:cs">
  <xsl:output method="xml" indent="yes"/>
  <msxsl:script language="C#" implements-prefix="cs">
    <![CDATA[
      public string datenow()
     {
        return(DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"));
     }
     ]]>
    </msxsl:script>
      <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Apple">
      <xsl:copy>
      <xsl:value-of select="cs:datenow()"/>
      </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Resulting Output:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <Apple>2012-02-22T18:03:12Z</Apple>
</root>

The script may reside in a same file (like I have it in my sample XSLT code) or if the code triggering XSLTransformation is C# then move the same code in the calling place :)

Rookie Programmer Aravind
  • 11,952
  • 23
  • 81
  • 114
  • I would uprate the solution but don't have enough rep to do so :( – Mike Feb 22 '12 at 14:20
  • 2
    @infantprogrammer'Aravind': +1 for a correct answer. Do note, however, that use of inline `` isn't recommended in cases of a server system under heavy use and in such case it is better to use an extension object and its public methods. The issue with inline `` is that `XslCompiledTransform` generates code for the script dynamically, in dynamic assemblies. If a transformation is repeatedly performed then the same scripts generate new dynamic dlls -- over and over again -- this eventually consumes almost all of the available memory and requires recycling. – Dimitre Novatchev Feb 22 '12 at 14:28
  • @DimitreNovatchev, really valuable comment :) I indeed faced an issue due to this behavior of code. :) a clean up tool used to delete junk dlls, which caused my transformation process to halt in the middle .. later as per your suggestion when I moved that code to new class under calling code helped resolving the issue :) – Rookie Programmer Aravind Feb 22 '12 at 14:35
  • Note: Not all xsl interpreters support C# scripting. – Jay Aug 06 '15 at 15:58
  • You might want to use DateTime.UtcNow. DateTime.Now will return local time and you're formatting it as UTC. – dtroy Feb 05 '16 at 06:14
7

It's better to pass current datetime from your XML engine. Declare <xsl:param name="current-datetime"/> in your xsl:stylesheet, and pass the value from processor.

Kirill Polishchuk
  • 54,804
  • 11
  • 122
  • 125
1

You'll better pass the current data as an input / xsl:param to the template.

The XSLT aims to be purely functional language; that is, all templates / functions should conform to e.g. the following condition: If a pure function is called with parameters that cause no side-effects, the result is constant with respect to that parameter list (sometimes called referential transparency), i.e. if the pure function is again called with the same parameters, the same result will be returned (this can enable caching optimizations such as memoization).

Although there are workarounds on this (as InfantPro'Aravind' pointed out), it is not recommended to do such things; by doing it, you're ruining one of the most significant XSLT benefits.

RobH
  • 3,604
  • 1
  • 23
  • 46
penartur
  • 9,792
  • 5
  • 39
  • 50