我有以下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>
我正在尝试编写一个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>
我需要游戏节点保持当前的顺序,所以我不确定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>
答案 0 :(得分:2)
我希望有一种比这更好的方法:
<xsl:template match="game">
<xsl:copy>
<xsl:variable name="time" select="@startTime" />
<xsl:for-each select="//game">
<xsl:sort select="@startTime" />
<xsl:if test="current()/@startTime = $time">
<xsl:attribute name="id">
<xsl:value-of select="position()"/>
</xsl:attribute>
</xsl:if>
</xsl:for-each>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
答案 1 :(得分: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,':')) < $current_time]) + 1"/>
</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
您也将获得所需的结果。此方法不使用排序,但每个条目计算当前条目下的所有条目。这是一个非常有趣的任务,因为我今天学到了令人惊讶的事实你无法比较XSLT 1.0中的字符串!尽管保留了原始模板的整体结构(与@Rubens的解决方案相比),但它需要将时间字符串转换为数字。当然,这很不方便。但是,您可能需要在其他解决方案中添加一些额外的字符串功能,以使其在10:00之前的时间内保持稳定。
顺便说一句:如果时间戳多次出现,则编号对应于带有间隙的排名(而不是没有间隙的密集排名)。