Date operations on xsl 1.0

后端 未结 2 1062
我在风中等你
我在风中等你 2020-11-28 15:25

I need to get 3 days before and after a given date defined in a variable, and store each one of them in a new individual variable in xsl 1.0. i can\'t use any extensions or

相关标签:
2条回答
  • 2020-11-28 16:04

    SAXON 6.5.5 supports the EXSLT extensions, but the date:add-duration() from dates and times module — which would solve your problem elegantly — is not implemented.

    However, you can directly use Java objects from within XSLT with Saxon:

    You can also use a short-cut technique of binding external Java classes, by making the class name part of the namespace URI.

    With the short-cut technique, the URI for the namespace identifies the class where the external function will be found. The namespace URI must either be "java:" followed by the fully-qualified class name (for example xmlns:date="java:java.util.Date") ...

    Quoting from this post, the method for adding days to dates in Java is

    String dt = "2008-01-01";  // Start date
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    Calendar c = Calendar.getInstance();
    c.setTime(sdf.parse(dt));
    c.add(Calendar.DATE, 1);  // number of days to add
    dt = sdf.format(c.getTime());  // dt is now the new date
    

    the XSLT version could look something like this (untested):

    <xsl:stylesheet
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:simple-date-format:="java:java.text.SimpleDateFormat"
      xmlns:calendar="java:java.util.Calendar"
    >
    
      <xsl:template name="date-add-days">
        <xsl:param name="input" />
        <xsl:param name="days" />
    
        <xsl:if test="
          function-available('simple-date-format:new') 
          and function-available('calendar:get-instance')
        ">
          <xsl:variable name="sdf"  select="simple-date-format:new('yyyy-MM-dd')" />
          <xsl:variable name="cal"  select="calendar:get-instance()" />
    
          <xsl:variable name="time" select="simple-date-format:parse($sdf, $input)" />
          <xsl:variable name="tmp1" select="calendar:set-time($cal, $time)" />
          <xsl:variable name="tmp2" select="calendar:add($cal, calendar:DATE(), number($days))" />
          <xsl:variable name="res" select="calendar:get-time($cal)" />
    
          <xsl:value-of select="simple-date-format:format($sdf, $res)" />
        </xsl:if>
      </xsl:template>
    
    </xsl:stylesheet>
    

    With regard to interacting with Java classes and objects from XPath:

    • From: http://saxon.sourceforge.net/saxon6.5.5/extensibility.html
      • The system function function-available(String name) returns true if there appears to be a method available with the right name.
      • If the method is a constructor, the XPath value is of type "wrapped Java object". The only way of using this is by passing it to another external function [...]
      • If the result is any other Java object (including null), it is returned as a "wrapped Java object".
    • From http://www.saxonica.com/documentation/extensibility/functions/staticmethods.html
      • Static methods can be called directly.
    • From http://www.saxonica.com/documentation/extensibility/functions/instance-methods.html)
      • Instance-level methods (that is, non-static methods) are called by supplying an extra first argument of type Java Object which is the object on which the method is to be invoked.

    I'm not sure of the method name format. The Saxon 6.5.5 documentation seems to imply dashed format (toString() becomes to-string()), so I've been using this here. Maybe calendar:set-time() must actually called calendar:setTime(), try it out & fix my answer.

    0 讨论(0)
  • 2020-11-28 16:13

    Adding/subtracting number of days to/from date in pure XSLT 1.0:

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:param name="givenDate" select="'2014-05-13T00:00:00'"/>
    <xsl:param name="daysDiff" select="-3"/>
    
    <xsl:variable name="JDN">
        <xsl:call-template name="JDN">
            <xsl:with-param name="date" select="$givenDate" />
        </xsl:call-template>
    </xsl:variable>
    
    <xsl:variable name="newDate">
        <xsl:call-template name="GD">
            <xsl:with-param name="JDN" select="$JDN + $daysDiff" />
        </xsl:call-template>
    </xsl:variable>
    
    
    <xsl:template match="/">
        <output>
            <GivenDate><xsl:value-of select="$givenDate"/></GivenDate>
            <NewDate><xsl:value-of select="$newDate"/></NewDate>
        </output>
    </xsl:template> 
    
    
    <xsl:template name="JDN">
        <xsl:param name="date"/>
        <xsl:param name="year" select="substring($date, 1, 4)"/>
        <xsl:param name="month" select="substring($date, 6, 2)"/>
        <xsl:param name="day" select="substring($date, 9, 2)"/>
        <xsl:param name="a" select="floor((14 - $month) div 12)"/>
        <xsl:param name="y" select="$year + 4800 - $a"/>
        <xsl:param name="m" select="$month + 12*$a - 3"/>
        <xsl:value-of select="$day + floor((153*$m + 2) div 5) + 365*$y + floor($y div 4) - floor($y div 100) + floor($y div 400) - 32045" />
    </xsl:template> 
    
    <xsl:template name="GD">
        <xsl:param name="JDN"/>
        <xsl:param name="f" select="$JDN + 1401 + floor((floor((4 * $JDN + 274277) div 146097) * 3) div 4) - 38"/>
        <xsl:param name="e" select="4*$f + 3"/>
        <xsl:param name="g" select="floor(($e mod 1461) div 4)"/>
        <xsl:param name="h" select="5*$g + 2"/>
        <xsl:param name="D" select="floor(($h mod 153) div 5 ) + 1"/>
        <xsl:param name="M" select="(floor($h div 153) + 2) mod 12 + 1"/>
        <xsl:param name="Y" select="floor($e div 1461) - 4716 + floor((14 - $M) div 12)"/>
        <xsl:param name="MM" select="substring(100 + $M, 2)"/>
        <xsl:param name="DD" select="substring(100 + $D, 2)"/>
        <xsl:value-of select="concat($Y, '-', $MM, '-', $DD)" />
    </xsl:template>     
    
    </xsl:stylesheet>
    

    Result:

    <?xml version="1.0" encoding="UTF-8"?>
    <output>
       <GivenDate>2014-05-13T00:00:00</GivenDate>
       <NewDate>2014-05-10</NewDate>
    </output>
    

    --
    Note that the givenDate's parameter value is a string and as such must be wrapped in single quotes.

    0 讨论(0)
提交回复
热议问题