9

我的数据模型如下:

<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:获取最新日期,但它没有给我任何价值。

我试图让最年轻的玩家传递给外部函数。

我在 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。但它是空白的。

4

2 回答 2

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
于 2012-10-01T15:52:05.487 回答
2

链接参考中的日期排序“有效”的原因是它采用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>
于 2012-10-02T09:49:02.483 回答