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

如何使用XSLT 1.0计算XML中numbers元素的数值总和?

解决XSLT 1.0中逗号分隔数字的求和问题

嘿,我来帮你搞定这个问题~你之前用str:tokenize()没得到预期结果,核心原因是这个函数是XSLT 2.0及更高版本才支持的,XSLT 1.0根本没有这个内置函数,所以得换个1.0兼容的实现方式。

下面给你两种可行的解决方案,都是XSLT 1.0原生支持的:


方法一:递归拆分字符串+节点集求和

这种方法先把逗号分隔的字符串拆成独立的数字节点,再用sum()函数计算总和。适合需要保留拆分后数字的场景,也方便扩展其他操作。

完整XSLT代码:

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:exsl="http://exslt.org/common">
    <xsl:output method="xml" indent="yes"/>

    <!-- 递归模板:拆分逗号分隔字符串,生成<number>节点 -->
    <xsl:template name="split-numbers">
        <xsl:param name="input-string"/>
        <xsl:choose>
            <!-- 还有逗号,拆分第一个数字后递归处理剩余部分 -->
            <xsl:when test="contains($input-string, ',')">
                <number>
                    <xsl:value-of select="normalize-space(substring-before($input-string, ','))"/>
                </number>
                <xsl:call-template name="split-numbers">
                    <xsl:with-param name="input-string" select="substring-after($input-string, ',')"/>
                </xsl:call-template>
            </xsl:when>
            <!-- 处理最后一个数字(或单个数字) -->
            <xsl:otherwise>
                <number>
                    <xsl:value-of select="normalize-space($input-string)"/>
                </number>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!-- 主模板:遍历用户信息并计算总和 -->
    <xsl:template match="/">
        <user-number-sums>
            <xsl:for-each select="documents/document/userData/userInfo">
                <user>
                    <name><xsl:value-of select="user"/></name>
                    <total>
                        <!-- 调用拆分模板生成数字节点,再转换为节点集求和 -->
                        <xsl:variable name="number-nodes">
                            <xsl:call-template name="split-numbers">
                                <xsl:with-param name="input-string" select="numbers"/>
                            </xsl:call-template>
                        </xsl:variable>
                        <xsl:value-of select="sum(exsl:node-set($number-nodes)/number)"/>
                    </total>
                </user>
            </xsl:for-each>
        </user-number-sums>
    </xsl:template>
</xsl:stylesheet>

关键细节:

  • normalize-space():处理数字前后可能存在的空格(如果你的数据里有的话),避免求和出错。
  • exsl:node-set():XSLT 1.0中,变量里的临时节点不能直接被sum()访问,需要用这个EXSLT函数把它转换成可遍历的节点集。大部分主流XSLT处理器(比如Saxon、Xalan)都支持这个扩展。

方法二:递归直接求和(无需节点集)

如果不需要保留拆分后的数字,只想直接得到总和,这种方法更高效,也不需要依赖EXSLT扩展。

核心是写一个递归模板,每次拆分出一个数字并累加到总和里:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <!-- 递归模板:直接计算逗号分隔字符串的数字总和 -->
    <xsl:template name="compute-sum">
        <xsl:param name="input-string"/>
        <xsl:param name="running-total" select="0"/>
        <xsl:choose>
            <xsl:when test="contains($input-string, ',')">
                <!-- 拆分第一个数字,累加到总和后递归 -->
                <xsl:call-template name="compute-sum">
                    <xsl:with-param name="input-string" select="substring-after($input-string, ',')"/>
                    <xsl:with-param name="running-total" select="$running-total + number(normalize-space(substring-before($input-string, ',')))"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <!-- 加上最后一个数字,返回最终总和 -->
                <xsl:value-of select="$running-total + number(normalize-space($input-string))"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!-- 主模板:调用求和模板 -->
    <xsl:template match="/">
        <user-number-sums>
            <xsl:for-each select="documents/document/userData/userInfo">
                <user>
                    <name><xsl:value-of select="user"/></name>
                    <total>
                        <xsl:call-template name="compute-sum">
                            <xsl:with-param name="input-string" select="numbers"/>
                        </xsl:call-template>
                    </total>
                </user>
            </xsl:for-each>
        </user-number-sums>
    </xsl:template>
</xsl:stylesheet>

测试结果

用你提供的XML输入,两种方法都会输出正确的结果:

<user-number-sums>
  <user>
    <name>John</name>
    <total>0</total>
  </user>
  <user>
    <name>Susan</name>
    <total>16</total>
  </user>
</user-number-sums>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 10:29:08