2012-04-09 129 views

回答

2

您可以通過使用遞歸模板來做到這一點。這不是最好的解決方案,因爲這會受到堆棧溢出或內存不足錯誤的影響(如果您給它的日期間隔足夠大),但它可能是一個開始的地方。

下面的例子需要的第一件事是檢查生成的值並確保它是有效的日期(您可以在網上找到一些示例;我只是使用a sample from an open source project並在該示例中僅導入了該文件保持較短)。

然後,我們的想法是通過將一天添加到前一天,然後將一天添加到當前日期來生成日期。如果這一天溢出,您將在月份中添加一個,並從第1天開始重新開始。如果月份溢出,您將與年份相同,並從第1個月開始。理論上,唯一永不會溢出的是年份(但您會限制與間隔的最終值)。

您生成日期並驗證它。如果它是有效的並且尚未達到間隔的結束時間,則嘗試通過向其添加日期來生成另一個日期(這就是塊X中發生的情況)。

當你得到一個無效的值,然後溢出。它只能是一天或一個月(如上所述)。我首先檢查月份(方塊Y)。如果是這樣,我從第一個月的第一天開始,但是第二年開始。如果是溢出的那一天(塊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> 
+0

謝謝你,波格丹!這很酷,適合我! – 2012-04-27 09:11:45

0

不幸的是,XSLT 1.0本身並不適合這樣的任務,但其環境通常是這樣的。下面是一些方法我用自己:

  1. 最簡單的解決方案通常是做出這樣的列表中的輸入的一部分=)

  2. XSLT轉換通常是與特定一個較大的應用程序的一部分XSLT處理器,它允許使用特定手段來擴展。你可以編寫一個擴展函數(使用Java,Javascript,PHP,Python取決於處理器),它返回所需的節點集。另一個但類似的選擇是註冊一個「流」(至少PHP),並使用document函數獲取節點集,其中url爲app://Dates/listdates?start=a&end=b。缺點是樣式表與應用程序耦合,無法單獨開發。

  3. 大多數XSTL處理器都支持EXSLT擴展。您可以使用日期擴展來計算日期之間的天數,使用字符串擴展中的padding函數生成一個字符串長度,將字符串拆分爲空字符串以獲取(需要的長度的)標記列表並迭代列表使用node-set函數並使用date-add將當前節點位置添加到第一個日期。

  4. 按照Bogdan的建議,使用純XSLT和遞歸模板。