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

如何在不改变位置的前提下用XSLT去除重复ITEM段

ITEM节点按规则去重的XSLT解决方案

需求说明

移除重复的ITEM段,不改变原有节点位置,无需检查ITEM的子节点及值。现有XSLT仅检查ITEM段完全匹配,无法满足需求,还会导致ITEM字段位置错乱。

去重规则

  • 多个ITEM的N11和AR值相同时视为重复,保留任意一个;
  • 若同组(相同N11+AR)中存在带subnode子节点的ITEM,则仅保留该ITEM,移除其他同组ITEM。

输入示例

<?xml version="1.0" encoding="UTF-8"?>
<D02X001>
    <DOC BEGIN="1">
        <DC40 SEGMENT="1">
            <NAM>DC40</NAM>
        </DC40>
        <BXYH SEGMENT="1">
            <LDAT>date</LDAT>
            <UDAT>date1</UDAT>
            <BXYI SEGMENT="1">
                <TNR>123453</TNR>
                <ORT>1000</ORT>
                <ITEM SEGMENT="1">
                    <N11>6789</N11>
                    <AR>03</AR>
                </ITEM>
                <ITEM SEGMENT="1">
                    <N11>6789</N11>
                    <AR>03</AR>
                    <subnode>
                        <field1> 13</field1>
                    </subnode>
                </ITEM>
                <ITEM SEGMENT="1">
                    <N11>6789</N11>
                    <AR>03</AR>
                </ITEM>
                <ITEMNEW SEGMENT="1">
                    <N11>6789</N11>
                    <AR>03</AR>
                    <PQC>NU</PQC>
                    <QTY>3456</QTY>
                    <NUM/>
                    <ASCD/>
                </ITEMNEW>
            </BXYI>
            <BXYI SEGMENT="1">
                <TNR>123453</TNR>
                <ORT>1000</ORT>
                <ITEM SEGMENT="1">
                    <N11>6789</N11>
                    <AR>03</AR>
                </ITEM>
                <ITEM SEGMENT="1">
                    <N11>6789</N11>
                    <AR>03</AR>
                    <subnode>
                        <field1> 13</field1>
                    </subnode>
                </ITEM>
                <ITEM SEGMENT="1">
                    <N11>6789</N11>
                    <AR>03</AR>
                </ITEM>
                <ITEMNEW SEGMENT="1">
                    <N11>6789</N11>
                    <AR>03</AR>
                    <PQC>NU</PQC>
                    <QTY>3456</QTY>
                    <NUM/>
                    <ASCD/>
                </ITEMNEW>
            </BXYI>
        </BXYH>
    </DOC>
</D02X001>

输出示例

<?xml version="1.0" encoding="UTF-8"?>
<D02X001>
    <DOC BEGIN="1">
        <DC40 SEGMENT="1">
            <NAM>DC40</NAM>
        </DC40>
        <BXYH SEGMENT="1">
            <LDAT>date</LDAT>
            <UDAT>date1</UDAT>
            <BXYI SEGMENT="1">
                <TNR>123453</TNR>
                <ORT>1000</ORT>         
                <ITEM SEGMENT="1">
                    <N11>6789</N11>
                    <AR>03</AR>
                    <subnode>
                        <field1> 13</field1>
                    </subnode>
                </ITEM>     
                <ITEMNEW SEGMENT="1">
                    <N11>6789</N11>
                    <AR>03</AR>
                    <PQC>NU</PQC>
                    <QTY>3456</QTY>
                    <NUM/>
                    <ASCD/>
                </ITEMNEW>
            </BXYI>
            <BXYI SEGMENT="1">
                <TNR>123453</TNR>
                <ORT>1000</ORT>     
                <ITEM SEGMENT="1">
                    <N11>6789</N11>
                    <AR>03</AR>
                    <subnode>
                        <field1> 13</field1>
                    </subnode>
                </ITEM>     
                <ITEMNEW SEGMENT="1">
                    <N11>6789</N11>
                    <AR>03</AR>
                    <PQC>NU</PQC>
                    <QTY>3456</QTY>
                    <NUM/>
                    <ASCD/>
                </ITEMNEW>
            </BXYI>
        </BXYH>
    </DOC>
</D02X001>

现有XSLT问题

当前使用的XSLT存在两个核心问题:

  1. 全局key匹配所有BXYI/ITEM,会跨不同BXYI节点去重,违反了保留原位置的需求;
  2. 逻辑判断未正确优先保留带subnode的ITEM,且可能导致节点顺序错乱。

现有代码:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  expand-text="yes">
  
   <xsl:key name="item-by-N11-AR" match="BXYI/ITEM" composite="yes" use="N11, AR"/>

  <xsl:template match="BXYI/ITEM[not(key('item-by-N11-AR', (N11, AR))[subnode])][not(. is key('item-by-N11-AR', (N11, AR))[1])]"/>
  <xsl:template match="BXYI/ITEM[key('item-by-N11-AR', (N11, AR))[subnode]][not(. is key('item-by-N11-AR', (N11, AR))[subnode][1])]"/>

  <xsl:mode on-no-match="shallow-copy"/>

</xsl:stylesheet>

修正后的XSLT代码

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  expand-text="yes">

  <!-- 将key作用域限定在当前BXYI节点内,确保每组BXYI独立去重 -->
  <xsl:key name="item-by-N11-AR" match="ITEM" composite="yes" use="N11, AR" scope="parent::BXYI"/>

  <!-- 移除符合条件的重复ITEM:
       1. 同组存在带subnode的ITEM时,仅保留第一个出现的带subnode的,移除其他;
       2. 同组无subnode时,仅保留第一个出现的ITEM,移除其他 -->
  <xsl:template match="ITEM[
    let $group := key('item-by-N11-AR', (N11, AR))
    return
      ($group[subnode] and not(. is $group[subnode][1])) 
      or 
      (not($group[subnode]) and not(. is $group[1]))
  ]"/>

  <xsl:mode on-no-match="shallow-copy"/>

</xsl:stylesheet>

代码说明

  • 作用域限定:通过scope="parent::BXYI"将key的匹配范围限制在当前BXYI节点内,避免跨节点去重;
  • 优先级处理:优先保留带subnode的ITEM,若同组存在此类节点,仅保留第一个出现的;
  • 位置保留:仅移除重复节点,剩余节点保持原始顺序不变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 23:57:00