2010-01-04 96 views
1

我對XSLT有一些使用經驗,但現在我已經遇到了一個問題: 我需要檢查begin和enddate之間的期間是否完全覆蓋另一個期間。使用XSLT比較日期期間

這裏是XML的一部分:

<Parent ID="1"> 
    <StartDate>20050101</StartDate> 
    <EndDate>20060131</EndDate> 
    <Child ID="1"> 
    <StartDate>20050101</StartDate> 
    <EndDate>20081231</EndDate> 
    </Child> 
</Parent> 
<Parent ID="2"> 
    <StartDate>20060201</StartDate> 
    <EndDate>20071231</EndDate> 
    <Child ID="1"> 
    <StartDate>20050101</StartDate> 
    <EndDate>20081231</EndDate> 
    </Child> 
</Parent> 
<Parent ID="3"> 
    <StartDate>20080101</StartDate> 
    <EndDate>20081231<EndDate> 
    <Child ID="1"> 
    <StartDate>20050101</StartDate> 
    <EndDate>20081231</EndDate> 
    </Child> 
</Parent> 

所以我需要檢查,如果開始和家長的結束之間的週期由開始和兒童的結束之間的週期在XSLT完全覆蓋,並且寫Parent和Child ID的xml失敗。

有人能給我一個開始如何在XSLT中管理這個...?

我完全控制了XML的結構,因此當使用其他XML結構(使用相同數據)更容易時,我可以更改它。

非常感謝!

+0

爲什麼子節點的數據父的超集?這似乎是落後的。無論如何,要使用XML日期函數,您應該使用XML日期格式,而不是您自己的:http://www.w3schools.com/Schema/schema_dtypes_date.asp – Welbog 2010-01-04 17:04:37

+0

在這部分xml中,它們是超集,但在其他情況下在我的數據中是相反的。 日期是關鍵/關係的一部分,我需要檢查子記錄是否與一個或多個父母時期匹配。 我會將格式更改爲官方日期格式,並查看不同的XML日期函數thnx! – 2010-01-04 17:18:34

回答

2

使用簡單的字符串比較很容易,因爲你的日期格式是big-endian。這裏有一個快速的XSLT文件我寫了測試一下:

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

    <xsl:template match="/"> 
    <root> 
     <xsl:for-each select="//Parent"> 
     <parent> 
      <xsl:attribute name="id"> 
      <xsl:value-of select="@ID"/> 
      </xsl:attribute> 
      <xsl:choose> 
      <xsl:when test="(Child/StartDate &lt;= StartDate) and 
       (Child/EndDate &gt;= EndDate)"> 
       <xsl:text>OK</xsl:text> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:text>Not OK</xsl:text> 
      </xsl:otherwise> 
      </xsl:choose> 
     </parent> 
     </xsl:for-each> 
    </root> 
    </xsl:template> 
</xsl:stylesheet> 

顯然,您需要自己檢查,以確保StartDateEndDate兩個父母和孩子面前。

+0

一些挑剔的言論:)做''// Parent''是不必要的,''Parent''就夠了。 ''對於''是多餘的。另外,''測試中的括號不是絕對必要的,儘管它們增加了可讀性。 – Tomalak 2010-01-06 12:37:55

+0

@Tomalak:就像我通常在你挑選時告訴你的一樣,我試圖簡單地解釋一些事情,以減少讓人們對語法速記感到困惑的可能性,比如'{@id}'。雖然我會給你'// Parent'部分。那是因爲我稍微改變了原始格式。 – Welbog 2010-01-06 12:58:10

0

number(Child/StartDate) <= number(Parent/StartDate) and number(Child/EndDate) >= number(Parent/EndDate)怎麼了?

3

下面是一個例子做直接在XSLT 2.0和應與大多數日期定界符工作:

<?xml version="1.0" encoding="UTF-8"?> 
    <xsl:stylesheet version="2.0" 
      exclude-result-prefixes="functx xs" 
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
      xmlns:functx="http://www.functx.com" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

     <xsl:template match="/"> 
      <dates> 
       <dateBetween> 
        <xsl:choose> 
         <xsl:when test="functx:dateBetween('02-01-2009','01-01-2009','03-01-2009')=true()"> 
          <xsl:text>date lays between given dates</xsl:text> 
         </xsl:when> 
         <xsl:otherwise> 
          <xsl:text>date is not between given dates</xsl:text> 
         </xsl:otherwise> 
        </xsl:choose> 
       </dateBetween> 
       <currentDateBetween> 
        <xsl:choose> 
         <xsl:when test="functx:currentDateBetween('01-01-2000','01-01-2019')=true()"> 
          <xsl:text>current date lays between given dates</xsl:text> 
         </xsl:when> 
         <xsl:otherwise> 
          <xsl:text>current date is not between given dates</xsl:text> 
         </xsl:otherwise> 
        </xsl:choose> 
       </currentDateBetween> 
      </dates> 
     </xsl:template> 

     <!-- 
      Function:  dateBetween 
      Description: This function will check if a dates is between given dates 
      Input:   Input date, Input start date, Input end date 
      Output:   Boolean true if beween param 2 and 3 
      Created:  21-09-2012 by Raymond Meester 
     --> 
     <xsl:function name="functx:dateBetween"> 
      <xsl:param name="param1"/> 
      <xsl:param name="param2"/> 
      <xsl:param name="param3"/> 

      <xsl:variable name ="dateToCheck" select="functx:mmddyyyy-to-date($param1)"/>   
      <xsl:variable name ="startDate" select="functx:mmddyyyy-to-date($param2)"/> 
      <xsl:variable name ="endDate" select="functx:mmddyyyy-to-date($param3)"/>  
      <xsl:variable name ="true" as="xs:boolean" select="true()"/> 
      <xsl:variable name ="false" as="xs:boolean" select="false()"/>   

      <xsl:choose> 
       <xsl:when test="$startDate &lt; $dateToCheck and $dateToCheck &lt; $endDate"><xsl:value-of select="$true"/></xsl:when> 
       <xsl:otherwise><xsl:value-of select="$false"/></xsl:otherwise> 
      </xsl:choose> 

     </xsl:function> 

     <!-- 
      Function:  currentDateBetween 
      Description: This function will check if a dates is between given dates 
      Input:   Input date, Input start date, Input end date 
      Output:   Boolean true if beween param 2 and 3 
      Created:  21-09-2012 by Raymond Meester 
     -->  
     <xsl:function name="functx:currentDateBetween"> 
      <xsl:param name="param1"/> 
      <xsl:param name="param2"/> 

      <xsl:variable name ="startDate" select="functx:mmddyyyy-to-date($param1)"/> 
      <xsl:variable name ="endDate" select="functx:mmddyyyy-to-date($param2)"/>  
      <xsl:variable name ="true" as="xs:boolean" select="true()"/> 
      <xsl:variable name ="false" as="xs:boolean" select="false()"/>   

      <xsl:choose> 
       <xsl:when test="$startDate &lt; current-date() and current-date() &lt; $endDate"><xsl:value-of select="$true"/></xsl:when> 
       <xsl:otherwise><xsl:value-of select="$false"/></xsl:otherwise> 
      </xsl:choose> 

     </xsl:function> 

     <!-- 
      Function:  mmddyyyy-to-date 
      Description: The functx:mmddyyyy-to-date function converts $dateString into a valid xs:date value. The order of the digits in $dateString must be MMDDYYYY, but it can contain any (or no) delimiters between the digits. 
      Input:   Input string 
      Output:   Return date 
      Created:  2007-02-26 http://www.xsltfunctions.com/xsl/functx_mmddyyyy-to-date.html 
     -->  
     <xsl:function name="functx:mmddyyyy-to-date" as="xs:date?" 
       xmlns:functx="http://www.functx.com"> 
      <xsl:param name="dateString" as="xs:string?"/> 
      <xsl:sequence select="if (empty($dateString)) then() else if (not(matches($dateString,'^\D*(\d{2})\D*(\d{2})\D*(\d{4})\D*$'))) then error(xs:QName('functx:Invalid_Date_Format')) else xs:date(replace($dateString,'^\D*(\d{2})\D*(\d{2})\D*(\d{4})\D*$','$3-$1-$2'))"/> 
     </xsl:function> 

    </xsl:stylesheet>