2012-10-01 169 views
7

我的數據模型如下:獲取最新日期在XML記錄

<Club> 
<Captain> 
<Name></Name> 
<DateOfBirth>15-01-1985</DateOfBirth> 
</Captain> 
<PlayingStaff> 
<Player> 
<DateOfBirth>14-01-1993</DateOfBirth> 
</Player> 
<Player> 
<DateOfBirth>07-12-1975</DateOfBirth> 
</Player> 
<Player> 
<DateOfBirth>11-11-1991</DateOfBirth> 
</Player> 
</PlayingStaff> 
</Club> 

我一直在使用這裏給出的答案嘗試:XSLT: Getting the latest date但它不是給我的任何值。

我想讓最年輕的玩家傳遞給外部函數。

我在Biztalk的這樣做,所以我要堅持XSLT1

我的工作至今如下:

<xsl:variable name="youngestPlayer"> 
      <xsl:for-each select="$ClubRoot/*[local-name()='PlayingStaff']/*[local-name()='Player']"> 
       <xsl:sort select="./*[local-name()='DateOfBirth']" order="descending"/> 
       <xsl:if test="position() = 1"> 
        <xsl:value-of select="DateOfBirth"/> 
       </xsl:if> 
      </xsl:for-each> 
     </xsl:variable> 
     <xsl:variable name="IsYoungestPlayerUnderAgeLimit" select="externalfunctionreturningboolean"> 
      <xsl:element name="blahhh"><xsl:value-of select="$IsYoungestPlayerUnderAgeLimit"/></xsl:element> 
      <xsl:element name="blahhh"><xsl:value-of select="$youngestPlayer"/></xsl:element> 

這是一個大模板的一部分 - 我真的不能改變這種情況,但根腫病的值是「<xsl:variable name="ClubRoot" select="/*[1]"/>",以確保我能讀懂它的子節點。

我一直都想與

<blahhh>false</blahhh> 
<blahhh/> 

作爲我的調試值...所以我沒有拿起我期望的值

有人可以突出顯示我出錯的地方嗎?

從上面的數據中,我期望在我的youngestPlayer變量中的值爲14-01-1993。但它的空白。

回答

6

問題是,XSLT1.0並沒有真正的日期概念,所以您正在按照元素進行排序,就好像它們只是普通字符串一樣。如果你能確定的日期總是在格式DD-MM-YYYY你可以使用字符串操作的年,月,日

<xsl:sort select="number(substring(DateOfBirth, 7, 4))" order="descending"/> 
<xsl:sort select="number(substring(DateOfBirth, 3, 2))" order="descending"/> 
<xsl:sort select="number(substring(DateOfBirth, 1, 2))" order="descending"/> 

所以進行排序,給出下面的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/Club"> 
     <xsl:for-each select="PlayingStaff/Player"> 
     <xsl:sort select="number(substring(DateOfBirth, 7, 4))" order="descending"/> 
     <xsl:sort select="number(substring(DateOfBirth, 3, 2))" order="descending"/> 
     <xsl:sort select="number(substring(DateOfBirth, 1, 2))" order="descending"/> 

     <xsl:if test="position() = 1"> 
      <xsl:value-of select="DateOfBirth"/> 
     </xsl:if> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

當適用於您的XML,下面是輸出

14-01-1993 
+2

通過使用translate()函數,可以減少XSL的計數:排序指令從3到1,AND簡化'xsl:sort/@ select表達式'。 –

1

爲什麼日期的引用鏈接排序「工作」,是因爲它是在yyyy-MM-dd格式,而不是爲y的原因我們的dd-MM-yyyy格式。

Tim C/Sean的提議的一個替代方法是使用C#腳本函數(因爲您使用的是BizTalk)將日期恢復爲可按您的鏈接排序的日期 - 但請注意,這不太可能像原生xslt函數。還要注意,你可能需要在你的變量上使用msxsl:node-set來告訴BizTalk的解析器這是一個片段。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp" 
       xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
       exclude-result-prefixes="userCSharp msxsl" 
       > 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
     <xsl:variable name="ClubRoot" select="/*[1]"/> 
     <xsl:variable name="orderedPlayers"> 
      <xsl:for-each select="msxsl:node-set($ClubRoot)/*[local-name()='PlayingStaff']/*[local-name()='Player']"> 
       <xsl:sort select="userCSharp:makeSortableDate(string(*[local-name()='DateOfBirth']), 'dd-MM-yyyy')" order="descending"/> 
       <xsl:copy-of select="node() | @*"/> 
      </xsl:for-each> 
     </xsl:variable> 

     <xsl:variable name="youngestPlayerDOB"> 
      <xsl:value-of select="msxsl:node-set($orderedPlayers)[1]/DateOfBirth/text()" /> 
     </xsl:variable> 

     <xsl:element name="blahhh"> 
      <xsl:variable name="IsYoungestPlayerUnderAgeLimit" select="userCSharp:externalfunctionreturningboolean($youngestPlayerDOB)" /> 
      <xsl:value-of select="$IsYoungestPlayerUnderAgeLimit"/> 
     </xsl:element> 
     <xsl:element name="blahhh"> 
      <xsl:value-of select="$youngestPlayerDOB"/> 
     </xsl:element> 
    </xsl:template> 

    <msxsl:script language="C#" implements-prefix="userCSharp"> 
     <![CDATA[ 
     public System.String makeSortableDate(System.String yourDate, string format) 
     { 
      return (System.DateTime.ParseExact(yourDate, format, System.Globalization.CultureInfo.InvariantCulture).ToString("yyyy-MM-dd")); 
     } 

     public bool externalfunctionreturningboolean(System.String dobString) 
     { 
      System.DateTime someDate; 
      if (System.DateTime.TryParse(dobString, out someDate)) 
      { 
       // NB : Doesn't work out leap years correctly! 
       if ((System.DateTime.Now - someDate).Days < 21 * 365.25) 
       { 
        return true; 
       } 
      } 
      return false; 
     } 
    ]]> 
    </msxsl:script> 

</xsl:stylesheet> 

我已經採取了一個黑客在功能和猜測未成年上限爲21以上的回報

<blahhh>true</blahhh> 
<blahhh>14-01-1993</blahhh>