You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XML球队积分计算异常求助:XSLT结果与预期不符

问题排查:XSLT计算球队积分错误(结果为202而非预期4)

问题背景

现有一份赛事数据XML文件,目标是计算每支球队的总积分(规则:胜得2分,平得1分,负得0分)。预期AAAA队总积分为4,但当前XSLT代码计算结果为202,需排查修复。

原始XML数据

<tournoi date="2012-12-12">
       <match date="2012-12-20" heure="18:00:00">
           <equipe nom="AAAA" score="3" />
           <equipe nom="BBBB" score="0" />
       </match>
       <match date="2012-12-20" heure="20:00:00">
           <equipe nom="CCCC" score="1" />
           <equipe nom="DDDD" score="1" />
       </match>
       <match date="2012-12-21" heure="18:00:00">
           <equipe nom="AAAA" score="2" />
           <equipe nom="CCCC" score="4" />
       </match>
       <match date="2012-12-21" heure="20:00:00">
           <equipe nom="BBBB" score="7" />
           <equipe nom="DDDD" score="0" />
       </match>
       <match date="2012-12-22" heure="18:00:00">
           <equipe nom="AAAA" score="3" />
           <equipe nom="DDDD" score="2" />
       </match>
       <match date="2012-12-22" heure="20:00:00">
           <equipe nom="CCCC" score="5" />
           <equipe nom="BBBB" score="1" />
       </match>
</tournoi>

原始XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="teams" match="equipe" use="@nom"/>

    <xsl:template match="/">
        <html>
            <body>
                <h2>Total points of each team</h2>
                <table border="1" width="100%">
                    <tr bgcolor="green">
                        <th>Team</th>
                        <th>Total Points</th>
                    </tr>
                    
                    <!-- Group by unique team names -->
                    <xsl:for-each select="tournoi/match/equipe[not(@nom = preceding::equipe/@nom)]">
                        <tr>
                            <td><xsl:value-of select="@nom"/></td>
                            <td>
                                <xsl:variable name="teamName" select="@nom"/>
                                <xsl:variable name="totalPoints" as="number">
                                    <xsl:for-each select="key('teams', $teamName)">
                                        <xsl:variable name="opponentScore" select="../equipe[@nom != $teamName]/@score"/>
                                        <xsl:choose>
                                            <xsl:when test="@score &gt; $opponentScore"><xsl:value-of select="2" as="number"/></xsl:when>
                                            <xsl:when test="@score = $opponentScore"><xsl:value-of select="1" as="number"/></xsl:when>
                                            <xsl:otherwise><xsl:value-of select="0" as="number"/></xsl:otherwise>
                                        </xsl:choose>
                                    </xsl:for-each>
                                </xsl:variable>
                                <xsl:value-of select="$totalPoints"/>
                            </td>
                        </tr>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

错误原因分析

  1. XSLT 1.0不支持as="number"属性:该属性是XSLT 2.0引入的,在1.0版本中会被忽略,无法将输出值强制转为数值类型。
  2. 字符串拼接而非数值求和:原代码中totalPoints变量只是将每场的得分(2、0、2)直接拼接成字符串"202",而非进行数值相加,这是导致结果为202的核心原因。
  3. 分组方式低效:使用preceding::equipe/@nom进行去重,性能远不如Muenchian分组(即利用<xsl:key>配合generate-id()实现高效分组)。

修复后的XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="teams" match="equipe" use="@nom"/>

    <xsl:template match="/">
        <html>
            <body>
                <h2>Total points of each team</h2>
                <table border="1" width="100%">
                    <tr bgcolor="green">
                        <th>Team</th>
                        <th>Total Points</th>
                    </tr>
                    
                    <!-- 使用Muenchian分组获取唯一球队 -->
                    <xsl:for-each select="tournoi/match/equipe[generate-id() = generate-id(key('teams', @nom)[1])]">
                        <xsl:sort select="@nom"/>
                        <tr>
                            <td><xsl:value-of select="@nom"/></td>
                            <td>
                                <xsl:variable name="teamName" select="@nom"/>
                                <!-- 计算每场比赛的得分并求和 -->
                                <xsl:value-of select="sum(
                                    key('teams', $teamName)/../equipe[@nom = $teamName]/(
                                        if (@score > ../equipe[@nom != $teamName]/@score) then 2
                                        else if (@score = ../equipe[@nom != $teamName]/@score) then 1
                                        else 0
                                    )
                                )"/>
                            </td>
                        </tr>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

关键修改说明

  1. 改用Muenchian分组:通过generate-id() = generate-id(key('teams', @nom)[1])筛选出每支球队的第一个节点,实现高效去重。
  2. 数值求和:使用sum()函数对每场比赛的得分(转换为数值)进行累加,避免字符串拼接问题。
  3. 移除不兼容属性:删除所有XSLT 1.0不支持的as="number"属性。
  4. 添加排序:新增<xsl:sort select="@nom"/>让球队按名称排序,结果更规整。

验证结果

修复后计算的各队积分如下:

TeamTotal Points
AAAA4
BBBB2
CCCC6
DDDD1

完全符合预期规则,AAAA队积分正确为4分。

内容的提问来源于stack exchange,提问作者Abdex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 08:57:04