没有排序的XSLT Number节点

Das*_*ave 5 sorting xslt xslt-1.0

我有以下xml:

<policy>
    <games>
         <game startTime="11:00"/>
         <game startTime="11:20"/>
         <game startTime="11:40"/>
    </games>
    <games>
         <game startTime="11:10"/>
         <game startTime="11:30"/>
         <game startTime="11:50"/>
    </games>
</Policy>
Run Code Online (Sandbox Code Playgroud)

我正在尝试编写一个xslt,它将为每个游戏节点添加一个新属性,并按时间顺序添加值,例如

<policy>
    <games>
         <game startTime="11:00" id="1"/>
         <game startTime="11:20" id="3"/>
         <game startTime="11:40" id="5"/>
    </games>
    <games>
         <game startTime="11:10" id="2"/>
         <game startTime="11:30" id="4"/>
         <game startTime="11:50" id="6"/>
    </games>
</policy>
Run Code Online (Sandbox Code Playgroud)

我需要游戏节点保持当前的顺序,所以我不确定xsl:sort是否可行.

目前我有这个,显然只是按当前顺序编号,不会考虑时间属性:

<xsl:template match="game">
    <xsl:copy>
      <xsl:attribute name="id">
        <xsl:value-of select="count(preceding::game) + 1"/>
      </xsl:attribute>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

Mar*_*ert 1

如果您将匹配模板替换为

<xsl:template match="game">
  <xsl:variable name="current_time" select="number(substring-before(@startTime,':'))*60 + number(substring-after(@startTime,':'))"/>
  <xsl:copy>
    <xsl:attribute name="id">
      <xsl:value-of select="count(../../games/game[number(substring-before(@startTime,':'))*60 + number(substring-after(@startTime,':')) &lt; $current_time]) + 1"/>
    </xsl:attribute>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

你也会得到想要的结果。此方法不使用排序,而是对每个条目计算当前条目下方的所有条目。这是一项非常有趣的任务,因为我今天了解到一个令人惊奇的事实:您无法比较 XSLT 1.0 中的字符串!尽管保留了原始模板的整体结构(与@Rubens 的解决方案相比),但它需要将时间字符串转换为数字。当然,这很不方便。但是,您可能需要向其他解决方案添加一些额外的字符串功能,以使其在 10:00 点之前的时间方面也具有鲁棒性。

顺便说一句:如果时间戳出现多次,则编号对应于有间隙的排名(而不是没有间隙的密集排名)。