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

在XPath谓词中使用distinct-values:XML重复节点集过滤问题

嘿,我来帮你搞定这个XPath 2.0过滤重复节点的问题!先补全你的示例XML方便演示(假设第三个card是不同的条目):

<?xml version="1.0" encoding="utf-8"?>
<test>
  <card>
    <TimeCard>1234</TimeCard>
    <tax>HST</tax>
    <adjAmt>-112</adjAmt>
  </card>
  <card>
    <TimeCard>1234</TimeCard>
    <tax>GST</tax>
    <adjAmt>-112</adjAmt>
  </card>
  <card>
    <TimeCard>5678</TimeCard>
    <tax>HST</tax>
    <adjAmt>-200</adjAmt>
  </card>
</test>

从你的示例来看,核心需求应该是基于TimeCard和adjAmt的组合值去重(前两个card的这两个字段完全一致,只有tax不同),下面给你两种实用的XPath 2.0方案:

方案1:用for-each-group分组取唯一值(推荐)

XPath 2.0支持for-each-group语法,可以直接按指定字段分组后取每组的第一个节点:

for $group in /test/card 
group by concat(TimeCard, '|', adjAmt) 
return $group[1]
  • 这里用concat(TimeCard, '|', adjAmt)把两个字段拼接成唯一分组键(用|分隔是避免字段值本身包含特殊字符导致冲突)
  • $group[1]表示保留每组的第一个节点,如果想保留最后一个,改成$group[last()]即可

方案2:用节点比较过滤重复项

如果你习惯用传统的节点遍历写法,也可以这样写:

/test/card[not(. is following-sibling::card[TimeCard=current()/TimeCard and adjAmt=current()/adjAmt][1])]

这个逻辑是:只保留那些后面没有相同TimeCard+adjAmt组合节点的条目,本质上也是去重。

额外场景:全节点内容去重

如果你的需求是严格判断整个card节点的所有内容(包括tax)是否完全重复,可以用deep-equal函数:

/test/card[not(. is following-sibling::card[deep-equal(., current())][1])]

deep-equal会递归比较两个节点的结构和所有子节点值,只有完全一致才会被判定为重复。

如果你的去重逻辑有其他调整(比如按更多字段分组),只要修改分组键或者比较条件就可以啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:38:56