如何在XSLT中对<xsl:for-each>的计算结果求和?
解决XSLT 1.0中对
<xsl:for-each>结果求和的问题 你遇到的问题核心是XSLT 1.0中无法直接对循环生成的结果树片段使用sum()函数,不过借助你正在使用的Xalan扩展函数xalan:node-set()就能轻松解决。下面是具体的实现方案:
简化后的解决方案代码
<xsl:stylesheet version="1.0" xmlns:xalan="http://xml.apache.org/xalan" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <!-- 第一步:收集所有符合条件的计算值到结果树片段 --> <xsl:variable name="calculated-values"> <!-- 直接筛选@encendido='1'的valor节点,简化循环条件 --> <xsl:for-each select="descendant::valor[@encendido='1']"> <!-- 简化计算逻辑:原表达式可约分,结果和你原来的计算完全一致 --> <value> <xsl:value-of select="@f div ../../../../@n"/> </value> </xsl:for-each> </xsl:variable> <!-- 第二步:将结果树片段转为节点集,再求和 --> <xsl:value-of select="sum(xalan:node-set($calculated-values)/value)"/> </xsl:template> </xsl:stylesheet>
为什么你的原有方法失效?
在XSLT 1.0中,当你在变量里嵌套循环或变量时,得到的是结果树片段(Result Tree Fragment),而不是标准的节点集。sum()函数只能作用于节点集,所以直接对这类变量使用sum()会没有输出。而xalan:node-set()的作用就是把结果树片段转换成可遍历的节点集,这样sum()就能正常计算总和了。
关于计算逻辑的简化
你原来的表达式:
($probadatos) * (../../@f div ../../../../@n)
其中$probadatos是@f div ../../@f,代入后可以约分:
(@f / ../../@f) * (../../@f / ../../../../@n) = @f / ../../../../@n
这样既简化了代码,也提升了计算效率,结果和你原来的计算完全一致。
测试验证
用你提供的XML测试,符合条件的valor节点是ProductoA(f=10)和ProductoC(f=30),最外层arbol的@n=100:
- 10/100 = 0.1
- 30/100 = 0.3
总和为0.4,正好是你需要的结果。
内容的提问来源于stack exchange,提问作者Gabriela M. Vázquez
相关产品推荐
相关产品推荐

