XPath如何使用count()按元素值分组统计出现次数?
原表达式错误原因
原有XPath存在两个核心问题,导致输出不符合预期:
- 未做去重处理:遍历对象是每一个
<name>节点,相同值对应多个节点时会重复输出多行 - 计数逻辑错误:
count(//$n)中$n是节点对象而非节点的文本值,XML里每个节点都是独立唯一的,因此所有计数结果恒为1
正确实现方案
支持XPath 2.0/3.0的环境(绝大多数现代XML处理工具,比如Saxon、BaseX、新版浏览器内置解析器)
直接使用distinct-values()先提取去重后的name值,再逐个统计对应节点数量即可,单条XPath就能实现需求:
for $nameVal in distinct-values(//names/name) return concat($nameVal, ': ', count(//names/name[. = $nameVal]))
执行逻辑说明:
- 用
distinct-values(//names/name)拿到所有不重复的name文本,从根源避免重复输出 - 对每一个唯一值,筛选出所有文本内容和它相等的
name节点做计数,得到准确的出现次数 - 按要求拼接成「值: 计数」的格式,输出结果和预期完全一致。
仅支持XPath 1.0的老旧环境
XPath 1.0没有内置去重函数,单条表达式很难优雅实现分组统计,建议搭配XSLT的Muenchian分组法完成需求,示例代码如下:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义按name值分组的索引 --> <xsl:key name="nameGroup" match="name" use="."/> <xsl:template match="/names"> <!-- 遍历每个分组的第一个节点,实现去重 --> <xsl:for-each select="name[count(. | key('nameGroup', .)[1]) = 1]"> <xsl:value-of select="concat(., ': ', count(key('nameGroup', .)))"/> <!-- 输出换行符分隔每条结果 --> <xsl:text> </xsl:text> </xsl:for-each> </xsl:template> </xsl:stylesheet>
内容的提问来源于stack exchange,提问作者ManiK
相关产品推荐
相关产品推荐

