获取xml记录中的最新日期

时间:2012-10-01 14:35:42

标签: xslt biztalk

我的数据模型如下:

<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>

这是大型模板的一部分 - 我无法真正改变这一点,但ClubRoot的值是“<xsl:variable name="ClubRoot" select="/*[1]"/>",以确保我可以读取它的子节点。”

我总是得到

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

作为我的调试值......所以我没有拿到我期望的值

有人可以突出显示我出错的地方吗?

根据上面的数据,我希望我的youngestPlayer变量中的值为14-01-1993。但它的空白。

2 个答案:

答案 0 :(得分:7)

问题是XSLT1.0并没有真正的日期概念,所以你有效地按 DateOfBirth 元素进行排序,好像它们只是普通字符串一样。如果您可以确定日期始终采用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

答案 1 :(得分:1)

链接引用中的日期排序“工作”的原因是因为它采用yyyy-MM-dd格式,而不是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>