【问题标题】:XSLT 1.0: Get the list of dates between two dates using XSLTXSLT 1.0:使用 XSLT 获取两个日期之间的日期列表
【发布时间】:2012-04-09 06:32:05
【问题描述】:

我需要获取两个日期之间的日期列表 - 例如我有开始日期 03302012 和结束日期 05302012,我需要像

这样的输出 03302012 03312012 04012012 04022012 ... 05282012 05292012 05302012
  • 请随意使用您的日期格式 - 我将自己进行转换。 非常感谢!

【问题讨论】:

  • 嗨,不要忘记接受答案。

标签: xml xslt xslt-1.0


【解决方案1】:

您可以通过使用递归模板来做到这一点。这不是最好的解决方案,因为这会导致堆栈溢出或内存不足错误(如果您给它的日期间隔足够大),但它可以作为一个起点。

下面的示例需要的第一件事是检查生成的值并确保它是有效日期(您可以在网上找到一些示例;我刚刚使用a sample from an open source project 并在示例中导入了文件使其更短)。

然后,想法是通过在前一天添加一天,然后在当前一天添加一天来生成日期,依此类推。如果这一天溢出,则在月份中添加一个并从第一天重新开始。如果月份溢出,则对年份执行相同操作并从第 1 个月开始。理论上唯一不会溢出的是年份(但你会限制这一点与区间的结束值)。

您生成一个日期并验证它。如果它是有效的并且还没有达到间隔的末尾,你尝试通过添加天数来生成另一个(这就是块 X 中发生的事情)。

当你得到一个无效的值时,就会溢出一些东西。它只能是日或月(如上所述)。我首先检查月份(块 Y)。如果是这种情况,我会从第 1 个月的第 1 天开始,但要从下一年开始。如果是溢出的那一天(区块Z),那么我从下个月的第一天开始。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:import href="http://www.getsymphony.com/download/xslt-utilities/source-code/54294/"/>
  <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

  <xsl:variable name="startDate" select="'03302012'" />  <!-- MMddyyyy format -->
  <xsl:variable name="endDate" select="'05302012'" /> <!-- MMddyyyy format -->

  <xsl:template match="/">
    <values>
      <xsl:call-template name="GenerateList">
        <xsl:with-param name="day" select="number(substring($startDate, 3, 2))" />
        <xsl:with-param name="month" select="number(substring($startDate, 1, 2))" />
        <xsl:with-param name="year" select="number(substring($startDate, 5))" />
      </xsl:call-template>
    </values>
  </xsl:template>

  <xsl:template name="GenerateList">
    <xsl:param name="day" select="1" />
    <xsl:param name="month" select="1" />
    <xsl:param name="year" select="1" />

    <!-- 1 = valid, 0 = invalid according to the imported file -->
    <xsl:variable name="validationResult">
      <xsl:call-template name="date-is-valid">
        <xsl:with-param name="day" select="$day"/>
        <xsl:with-param name="month" select="$month"/>
        <xsl:with-param name="year" select="$year"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:choose>
      <xsl:when test="$validationResult = 0">

        <xsl:choose>
          <xsl:when test="$month &gt; 12">
            <!-- block Y -->
            <xsl:call-template name="GenerateList">
              <xsl:with-param name="day" select="1" />
              <xsl:with-param name="month" select="1" />
              <xsl:with-param name="year" select="$year + 1" />
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <!-- block Z --> 
            <xsl:call-template name="GenerateList">
              <xsl:with-param name="day" select="1" />
              <xsl:with-param name="month" select="$month + 1" />
              <xsl:with-param name="year" select="$year" />
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>

      </xsl:when>
      <xsl:otherwise>
        <!-- block X -->
        <!-- same MMddyyyy format as the interval values -->
        <xsl:variable name="currentDate" select="concat(format-number($month, '00'), format-number($day, '00'), $year)" />
        <value>
          <xsl:value-of select="$currentDate" />
        </value>
        <xsl:if test="not($currentDate = $endDate)">
          <xsl:call-template name="GenerateList">
            <xsl:with-param name="day" select="$day + 1" />
            <xsl:with-param name="month" select="$month" />
            <xsl:with-param name="year" select="$year" />
          </xsl:call-template>
        </xsl:if>

      </xsl:otherwise>
    </xsl:choose>

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

【讨论】:

    【解决方案2】:

    不幸的是,XSLT 1.0 本身并不适合此类任务,但它的环境通常可以。以下是我自己使用的一些方法:

    1. 最简单的解决方案通常是将此类列表作为输入的一部分 =)

    2. XSLT 转换通常是具有特定 XSLT 处理器的大型应用程序的一部分,它允许使用特定方法对其进行扩展。您可以编写返回所需节点集的扩展函数(使用 Java、Javascript、PHP、Python,具体取决于处理器)。另一个但类似的选项是注册一个“流”(至少就 PHP 而言)并使用带有 app://Dates/listdates?start=a&amp;end=b 之类的 url 的 document 函数获取节点集。缺点是样式表与应用耦合,不能单独开发。

    3. 大多数 XSTL 处理器都支持 EXSLT 扩展。您可以使用日期扩展计算日期之间的天数,使用 padding 函数从字符串扩展生成长度的字符串,将字符串拆分为空字符串以获取令牌列表(具有所需长度)并迭代使用node-set 函数的列表并使用date-add 将当前节点位置添加到第一个日期。

    4. 按照 Bogdan 的建议,使用纯 XSLT 和递归模板。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-01
      • 2010-10-05
      • 1970-01-01
      • 2018-09-17
      • 2010-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多