如何在XQuery中对同一节点内空格/减号分隔的数字求和?
解决方案:XML 标签内数字计算转换
针对你需要将
XSLT 2.0 简洁实现
XSLT 2.0自带tokenize函数,处理字符串拆分非常方便:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 复制原XML的所有节点和属性,保留结构 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 专门处理<num>标签 --> <xsl:template match="num"> <xsl:copy> <xsl:choose> <!-- 处理连字符减法,比如"4-2" --> <xsl:when test="contains(., '-')"> <xsl:variable name="nums" select="tokenize(., '-')" /> <xsl:value-of select="number($nums[1]) - number($nums[2])" /> </xsl:when> <!-- 处理空格分隔的数字求和,比如"1 5 7" --> <xsl:otherwise> <xsl:variable name="nums" select="tokenize(., '\s+')" /> <xsl:value-of select="sum($nums)" /> </xsl:otherwise> </xsl:choose> </xsl:copy> </xsl:template> </xsl:stylesheet>
逻辑说明
- 第一个模板是身份模板,负责原样复制XML中除
外的所有内容,保证原有结构不变。 - 第二个模板匹配
标签: - 用
contains(., '-')判断是否为减法表达式,拆分后计算差值。 - 其他情况默认是空格分隔的数字,用
tokenize(., '\s+')拆分(支持多个连续空格),直接调用sum()求和。
- 用
XSLT 1.0 兼容方案
如果只能使用XSLT 1.0(无tokenize函数),可以用递归模板实现字符串拆分:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 身份模板:复制原结构 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 处理<num>标签 --> <xsl:template match="num"> <xsl:copy> <xsl:choose> <!-- 处理减法:拆分连字符两侧的数字 --> <xsl:when test="contains(., '-')"> <xsl:variable name="left" select="substring-before(., '-')" /> <xsl:variable name="right" select="substring-after(., '-')" /> <xsl:value-of select="number($left) - number($right)" /> </xsl:when> <!-- 调用递归求和模板处理空格分隔的数字 --> <xsl:otherwise> <xsl:call-template name="sum-space-separated"> <xsl:with-param name="str" select="." /> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:copy> </xsl:template> <!-- 递归模板:累加空格分隔的数字 --> <xsl:template name="sum-space-separated"> <xsl:param name="str" /> <xsl:param name="total" select="0" /> <xsl:choose> <!-- 还有空格,继续拆分累加 --> <xsl:when test="contains($str, ' ')"> <xsl:variable name="num" select="substring-before($str, ' ')" /> <xsl:call-template name="sum-space-separated"> <xsl:with-param name="str" select="normalize-space(substring-after($str, ' '))" /> <xsl:with-param name="total" select="$total + number($num)" /> </xsl:call-template> </xsl:when> <!-- 处理最后一个数字,返回总和 --> <xsl:otherwise> <xsl:value-of select="$total + number($str)" /> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
逻辑说明
- 减法部分用
substring-before和substring-after直接拆分数字。 - 求和部分通过递归模板逐次拆分第一个空格前的数字,累加到总和,
normalize-space用来处理连续空格的情况。
测试效果
输入XML:
<test> <num>1 5 7</num> <num>4-2</num> </test>
转换后输出:
<test> <num>13</num> <num>2</num> </test>
内容的提问来源于stack exchange,提问作者Ra1nForest
相关产品推荐
相关产品推荐

