3

I am trying to convert a date to a valid dateTime format, and then format the date. However i am running into transformation error after including xs:dateTime .

XML:

<?xml version="1.0" encoding="UTF-8"?>
<book>
    <title>doublebell</title>
    <timestamp>02/06/2014 13:51:09</timestamp>
</book>

XSLT:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xsl:output method="xml" version="1.0" encoding="UTF-8"
        indent="yes" />

    <xsl:template match="/">
        <myentity>
            <label>
                <xsl:value-of select="book/title" />
            </label>
            <date>
                <xsl:apply-templates select="book/timestamp" />
            </date>
        </myentity>
    </xsl:template>

    <xsl:template match="book/timestamp">
        <xsl:variable name="datestr">
            <xsl:value-of
                select="concat(substring(., 7, 4), '-', substring(., 4, 2), '-', substring(., 1, 2), 'T', substring(., 12))" />
        </xsl:variable>

        <!--<xsl:value-of select="$datestr" /> --> <!-- prints 2014-06-02T13:51:09 -->

        <xsl:variable name="date1" as="xs:dateTime" select="xs:dateTime($datestr)" />
        <xsl:variable name="formatteddate1">
            <xsl:value-of select="format-dateTime($date1, '[Y0001]-[M01]-[D01]')" />
        </xsl:variable>
        <xsl:value-of select="$formatteddate1" />

    </xsl:template>
</xsl:stylesheet>

I am getting XSLT transformation error while using "xs:dateTime". I could not figure out where i am doing wrong I am trying in the tool: http://www.freeformatter.com/xsl-transformer.html

PS: I can format the date just by using substring() and concat() functions. But i like to get the date in dateTime format so that i can increment the date by one day. Hence using the xs:dateTime() function to get the data in valid dateTime format. Edit: What i mean by valid dateTime format, is something of the datatype 'date' [like datatype String, number etc]

Please throw some pointers on what i am doing wrong

Update:

Even when i try this simple XSLT [based on SO - https://stackoverflow.com/questions/3885292/xslt-subtracting-days]

XSLT:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:fn="http://www.w3.org/xpath-functions">
    <xsl:template match="/">
        <xsl:value-of select="xs:date('2010-01-01')" />
    </xsl:template>
</xsl:stylesheet>

I am getting error. This time i also tried from my Apache Camel XSLT processor

Error details:

The first argument to the non-static Java function 'date' is not a valid object reference. javax.xml.transform.TransformerException: The first argument to the non-static Java function 'date' is not a valid object reference.

Update 1:

Looks like this has something to do with the XSLT transformation processor

http://www.freeformatter.com/xsl-transformer.html is not XSLT2.0 processor,

and my Apache Camel default processor is 1.0, and to process XSLT2.0, i need to explicitly mention transformer as some XSLT2.0 processor like Saxon 9.4.0.1

primary issue resolved

update 2 and update 3 are formatting date and increment date

Update 2: [i am not posting in a different thread as this is inter-related]

Finally i need to add a day to the input date, that was the reason why i went for xs:dateTime.

I am placing the code i tried, in case it will be useful for someone else in future. This time i am going for <xsl:call-template />

XML:

<?xml version="1.0" encoding="UTF-8"?>
<book>
    <title>doublebell</title>
    <timestamp>20131217-13:04:59-UTC</timestamp>
</book>

XSLT:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="text" />

    <xsl:template match="/">
        <date>
            <xsl:call-template name="formatdate">
                <xsl:with-param name="timestampstring" select="book/timestamp" />
            </xsl:call-template>
        </date>
    </xsl:template>


    <xsl:template name="formatdate">
        <xsl:param name="timestampstring" /> <!-- date is 20131217-13:04:59-UTC -->
        <xsl:variable name="datestr"> 
            <xsl:value-of
                select="concat(substring($timestampstring, 1, 4), '-', substring($timestampstring, 5, 2), '-', substring($timestampstring, 7, 2), 'T', substring($timestampstring,10, 8))" />
        </xsl:variable>
        date: <xsl:value-of select="$datestr" /><!-- date is 2013-12-17T13:04:59 -->
        date in custom format: <xsl:value-of select="format-dateTime($datestr, '[Y0001]-[M01]-[D01]')" />
        date+1: <xsl:value-of select="xs:dateTime($datestr) + xs:dayTimeDuration('P1D')" /> <!-- add one day -->
        date+3: <xsl:value-of select="xs:dateTime($datestr) + xs:dayTimeDuration('P3D')" /> <!-- add three days -->
    </xsl:template>

</xsl:stylesheet>

Output

date: 2013-12-17T13:04:59
        date in custom format: 2013-12-17
        date+1: 2013-12-18T13:04:59 
        date+3: 2013-12-20T13:04:59

Update 3

How to make adding the number of days, more generic? I did this way,

<!-- Made generic, increment interval can be passed as parameter -->
<xsl:template name="formatdateafterincrement">
    <xsl:param name="timestampstring" />
    <xsl:param name="incr" />
    <!-- input format: 'YYYYMMDD-HH:MM:SS-UTC' -->
    <!-- output format after date increment: YYYY-MM-DD -->
    <xsl:variable name="datestr">
        <xsl:value-of
            select="concat(substring($timestampstring, 1, 4), '-', substring($timestampstring, 5, 2), '-', substring($timestampstring, 7, 2), 'T', substring($timestampstring,10, 8))" />
    </xsl:variable>
    <xsl:variable name="datestrincr">
        <xsl:value-of select="xs:dateTime($datestr) + xs:dayTimeDuration($incr)" />
    </xsl:variable>
    <xsl:value-of select="format-dateTime($datestrincr, '[Y0001]-[M01]-[D01]')" />
</xsl:template>

<!-- how to call the template -->
<newdate>
    <xsl:call-template name="formatdateafterincrement">
        <xsl:with-param name="timestampstring" select="book/timestamp" />
        <xsl:with-param name="incr" select="'P1D'" /> <!-- one day -->
    </xsl:call-template>
</newdate>

http://xsltransform.net/ is a good XSLT 2.0 processor.

This works well. If someone has any suggestions, please share the same. I do not have a specific question. The questions are answered.

Community
  • 1
  • 1
spiderman
  • 10,892
  • 12
  • 50
  • 84
  • can someone tell me why the above code was not showing in code formatted style? I did the same way as I used to do the formatting. selecting the block of code and applying `CNTRL+K` – spiderman Feb 10 '14 at 16:30

2 Answers2

3

The reason is both the processors I was using to transform were XSLT1.0 processors.

The online tool which i mentioned: http://www.freeformatter.com/xsl-transformer.html is not XSLT2.0 processor. Also my application which is using Apache Camel has default XSLT processor 1.0. Using a XSLT 2.0 processor resolves the issue. So the error is related to using with a XSLT 1.0 processor

Also, just declaring <xsl:stylesheet version="2.0" has no meaning that you are using XSLT 2.0 processor. This was another wrong [illogical] assumption i had!

To run xs:date or xs:dateTime , I should use XSLT 2.0 processor

What i did in my Apache Camel configuration :

Added Saxon 9.4.0.1 as dependency [as jar or pom.xml dependency], and in my camel route, i made the changes:

<route..
<from uri=
<to uri="xslt:stylesheets/test.xslt?transformerFactoryClass=net.sf.saxon.TransformerFactoryImpl" />

spiderman
  • 10,892
  • 12
  • 50
  • 84
  • 2
    http://xsltransform.net/ can be useful to you, as it also has an XSLT 2.0 processor – Joel M. Lamsen Feb 07 '14 at 09:05
  • @JoelM.Lamsen this tool was very helpful, i played around with the xs:dateTime and other format fuctions. But i am seeing some weird output behavior for a scenario. I posted as a SO question here - http://stackoverflow.com/questions/21640457/xslt-getting-two-different-output-for-same-input-xml-for-same-xsl – spiderman Feb 08 '14 at 00:58
0

Ran your code and got <date>2014-06-02</date>

When you say "valid dateTime" what do you mean? Python dateTime? Php?

Paulb
  • 1,471
  • 2
  • 16
  • 39
  • What i mean by valid `dateTime` format, is something of the datatype 'datetime'. The datetime datatype that XSL transformer can understand so that i can increment or decrement the date [like datatype String, number etc) . I am using the XSLT in a java based application. Where did you run this code? – spiderman Feb 06 '14 at 23:54
  • The error triggers when i try to use ` xs:date ` or ` xs:dateTime ` – spiderman Feb 07 '14 at 00:01
  • Thanks for confirming that you got the output for the same code, that meant you ran with a different processor – spiderman Feb 07 '14 at 00:19
  • 1
    I ran it in OxygenXML.. on Linux. – Paulb Feb 07 '14 at 00:58
  • Thanks for trying it out in OxygenXML – spiderman Feb 07 '14 at 02:40