如何使用DataWeave或XSLT移除XML中的重复父节点及子节点
移除XML中重复的父节点及其子节点(DataWeave & XSLT实现)
我来帮你解决这个XML去重的问题——不管是用DataWeave还是XSLT,都有清晰的实现方式。你的需求是移除重复的<ns2:Parent>节点及其对应的<ns2:Children>子节点,只保留每个Parent值对应的唯一条目。假设你的XML结构是<ns1:Hierarchy>下交替出现<ns2:Parent>和<ns2:Children>节点(每个Parent紧跟对应的Children),下面是两种方案:
DataWeave 2.x 解决方案
这个方案先将Parent和Children节点配对,再根据Parent的值去重,最后重组XML结构,同时保留原有的命名空间:
%dw 2.0 output application/xml ns ns1 http://www.example.org/Hierarchy ns ns2 http://www.example.org/HierarchyResult --- ns1#Hierarchy: do { // 1. 将Hierarchy下的Parent和Children节点按顺序每两个分组,形成Parent-Children对 var parentChildPairs = payload.ns1#Hierarchy.*(ns2#Parent, ns2#Children) groupBy ((item, index) -> floor(index / 2)) mapObject ((value, key) -> { parent: value[0], children: value[1] }) // 2. 根据Parent的值分组,只保留每个组的第一个条目(去重) var uniquePairs = parentChildPairs groupBy ((pair) -> pair.parent) mapObject ((group) -> group[0]) // 3. 将去重后的Parent和Children节点重新组合到Hierarchy下 uniquePairs.*parent ++ uniquePairs.*children }
代码解释:
- 首先用
*(ns2#Parent, ns2#Children)获取所有Parent和Children节点,再按索引每两个分组,把相邻的Parent和Children配对成对象; - 通过
groupBy按Parent值分组,取每个组的第一个元素实现去重; - 最后把去重后的Parent和Children节点拼接起来,放回
<ns1:Hierarchy>根节点下。
XSLT 2.0 解决方案
这个方案使用XSLT的键(xsl:key)来分组Parent节点,只保留每个Parent值对应的第一个条目及其关联的Children:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="http://www.example.org/Hierarchy" xmlns:ns2="http://www.example.org/HierarchyResult"> <xsl:output method="xml" indent="yes"/> <!-- 定义键:根据Parent节点的文本值分组 --> <xsl:key name="parentKey" match="ns2:Parent" use="."/> <xsl:template match="/ns1:Hierarchy"> <xsl:copy> <!-- 复制根节点的所有属性(包括命名空间) --> <xsl:copy-of select="@*"/> <!-- 遍历每个唯一的Parent节点(仅保留每个组的第一个) --> <xsl:for-each select="ns2:Parent[count(. | key('parentKey', .)[1]) = 1]"> <!-- 复制当前Parent节点 --> <xsl:copy-of select="."/> <!-- 复制紧跟在该Parent之后的第一个Children节点 --> <xsl:copy-of select="following-sibling::ns2:Children[1]"/> </xsl:for-each> </xsl:copy> </xsl:template> <!-- 忽略其他无关的文本节点 --> <xsl:template match="text()"/> </xsl:stylesheet>
代码解释:
- 用
xsl:key创建一个基于Parent节点文本值的分组键; - 在根节点模板中,选择每个Parent组的第一个节点(通过
count(. | key('parentKey', .)[1]) = 1判断是否为组内第一个); - 复制该Parent节点,同时复制它后面紧跟的第一个Children节点,确保每个唯一Parent对应其关联的子节点。
内容的提问来源于stack exchange,提问作者SDE
相关产品推荐
相关产品推荐

