XSLT - 减去天数

12

使用XSLT是否可以从日期字段中减去N天?如果可以,请提供一个例子。


你使用的是哪个XSLT处理器? - Ondrej Tucny
XSLT 1.0还是XSLT 2.0?日期格式是什么? - user357812
好问题,+1。请查看我的答案,其中包含完整的XSLT 2.0解决方案。 - Dimitre Novatchev
5个回答

20

以下是在XSLT 2.0中实现此操作的演示:

<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="/">
  <xsl:variable name="vToday" select="current-date()"/>

  Today is: <xsl:sequence select="$vToday"/>
  30 days ago it was: <xsl:sequence select=
    "$vToday -30*xs:dayTimeDuration('P1D')"/>
  365 days ago it was: <xsl:sequence select=
    "$vToday -365*xs:dayTimeDuration('P1D')"/>
 </xsl:template>
</xsl:stylesheet>

当这个转换应用于任何XML文档(未使用),都会产生所需的正确结果:

  Today is: 2010-10-07-07:00
  30 days ago it was: 2010-09-07-07:00
  365 days ago it was: 2009-10-07-07:00

FYI... <xsl:variable name="vToday" select="current-date()"/> 会导致 Firefox 25 和 Chrome 30 中的空白页面。Firefox 给出了控制台错误 Component returned failure code: 0x80600005 [nsIXSLTProcessor.importStylesheet]。糟糕,显然你必须在 xsl:stylesheet 中指定 version="2.0"。我正在使用版本 1.0。 - doubleJ
FYI2...即使指定了 version=2.0,Chrome 30仍会生成空白页面。 然而,Firefox 25确实显示结果。 - doubleJ
@double,没有浏览器支持XSLT 2.0。您可以尝试使用SaxonCE 1.1。 - Dimitre Novatchev

11

使用 XSLT 2.0,这是很容易实现的。

XPATH 2.0 提供了许多关于日期/时间/持续时间的函数,这些函数也是 XSLT 2.0 的一部分。在这里可以找到这些函数

下面的示例减去了日期 2010-01-01 中的1天,得到了2009-12-31:

<?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">
<xsl:template match="/">
  <xsl:value-of select="xs:date('2010-01-01') - xs:dayTimeDuration('P1D')" />
</xsl:template>
</xsl:stylesheet>

2

嗯,XSLT可以分割字符串和解析数字,所以这是“可能的”。

然而,如果您能使用扩展函数并在另一种语言中实现它,那将更容易和高效。但是,这取决于所使用的XSLT引擎及其工作方式。

EXSLT可能拥有您需要的一切:http://www.exslt.org/date/functions/add/index.html


2
我可以看到所有提到的解决方案都是针对XSLT 2.0的。我有一个类似的解决方案,可以在XSLT 1.0中使用EXSLT date:add
例如:假设要减去的天数为365天,并且我们需要它作为默认开始日期。在这种情况下,我们必须以xs:dayTimeDuration格式提供持续时间为365天,即'-P365D'。
请参见以下代码。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:date="http://exslt.org/dates-and-times"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
extension-element-prefixes="date xs"
exclude-result-prefixes="date xs" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" />

    <xsl:template match="/">
      <xsl:variable name="vCurrDate" select="date:date-time()"/>
      <xsl:variable name="vDefaultStDate" select="(date:add($vCurrDate, '-P365D'))"/>
    </xsl:template>
</xsl:stylesheet>

1
不幸的是,很少有XSLT 1.0处理器支持EXSLT date:add()。对于纯粹的XSLT 1.0解决方案,没有扩展,请参见:https://stackoverflow.com/questions/23566734/date-operations-on-xsl-1-0/23569278#23569278 - michael.hor257k

0
<xsl:template name="dim" >

  <xsl:param name="y" />
  <xsl:param name="m"/>

  <xsl:choose>
     <xsl:when test="($m=1 or $m=3 or $m=5 or $m=7 or $m=8 or $m=10 or $m=12)" >
          31  
    </xsl:when>
    <xsl:when test="$m&gt;2">
         30 
   </xsl:when>
    <xsl:when test="($m=2) and (not($y mod 4=0)) or ($y mod 100=0) and (not($y mod 400=0))">
      28  
    </xsl:when>
    <xsl:otherwise>
       29
    </xsl:otherwise>
  </xsl:choose>

</xsl:template>


<xsl:template name="minusdays">
<xsl:param name="year" />
<xsl:param name="month" />
<xsl:param name="day"/>
<xsl:param name="days"/>
<xsl:variable name="lm" select="number($month)-1+number($month=1)*12"/>

<xsl:variable name="lmdays">
    <xsl:call-template name="dim">
       <xsl:with-param name="y" select="$year"/>
       <xsl:with-param name="m" select="$lm"/>
    </xsl:call-template>
</xsl:variable>

<xsl:choose>
    <xsl:when test="$days&lt;$day">
        <xsl:value-of select="$year"/>
       <xsl:if test="number($month)&lt;10">0</xsl:if>
       <xsl:value-of select="$month"/>
       <xsl:if test="($day - $days)&lt;10">0</xsl:if>
       <xsl:value-of select="$day - $days"/>
    </xsl:when>
    <xsl:otherwise>
        <xsl:call-template name="minusdays">
           <xsl:with-param name="year" 
           select="number($year)-number($month=1)"/>
         <xsl:with-param name="month" select="$lm" />
         <xsl:with-param name="day" select="$lmdays"/>
         <xsl:with-param name="days" select="$days - $day" />    
       </xsl:call-template>
    </xsl:otherwise>
</xsl:choose> 

</xsl:template>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接