XSLT删除重复OGS11段异常问题排查求助
问题:删除XML中重复的OGS11段(忽略SEQ1字段)
需求说明
- 针对多层
HEADER/SUBHEADER/ORDER结构,需在每个ORDER节点内处理重复的OGS11子节点 - 重复判定规则:忽略
OGS11/SEG/SEQ1字段的值,若OGS11下其余所有子节点的结构和内容完全一致,则判定为重复,仅保留第一个实例,删除后续重复项
输入XML
<?xml version="1.0" encoding="UTF-8"?> <ns0:HEADER xmlns:ns0="http://idenity.com"> <ns0:SUBHEADER> <ORDER> <HN> <field1>1233</field1> </HN> <GS1> <field1>1</field1> </GS1> <OGS11> <SEG> <SEQ1>21</SEQ1> <SEQ> <FIELD1>123</FIELD1> <FIELD2>EN</FIELD2> </SEQ> </SEG> <SEG2> <FIELD1>5</FIELD1> <SEQ> <FIELD2>123</FIELD2> <FIELD3>AS</FIELD3> </SEQ> </SEG2> </OGS11> <OGS11> <SEG> <SEQ1>22</SEQ1> <SEQ> <FIELD1>123</FIELD1> <FIELD2>EN</FIELD2> </SEQ> </SEG> <SEG2> <FIELD1>5</FIELD1> <SEQ> <FIELD2>123</FIELD2> <FIELD3>AS</FIELD3> </SEQ> </SEG2> </OGS11> <OGS11> <SEG> <SEQ1>23</SEQ1> <SEQ> <FIELD1>1234</FIELD1> <FIELD2>EN</FIELD2> </SEQ> </SEG> <SEG2> <FIELD1>5</FIELD1> <SEQ> <FIELD2>1414</FIELD2> <FIELD3>AS</FIELD3> </SEQ> </SEG2> </OGS11> <NEWSEGMENT> <FIELD1>123</FIELD1> </NEWSEGMENT> <NEWSEG1> <FIELD1>COUNT</FIELD1> </NEWSEG1> </ORDER> <ORDER> <HN> <field1>1234</field1> </HN> <GS1> <field1>1</field1> </GS1> <OGS11> <SEG> <SEQ1>21</SEQ1> <SEQ> <FIELD1>123</FIELD1> <FIELD2>EN</FIELD2> </SEQ> </SEG> <SEG2> <FIELD1>5</FIELD1> <SEQ> <FIELD2>123</FIELD2> <FIELD3>AS</FIELD3> </SEQ> </SEG2> </OGS11> <OGS11> <SEG> <SEQ1>22</SEQ1> <SEQ> <FIELD1>123</FIELD1> <FIELD2>EN</FIELD2> </SEQ> </SEG> <SEG2> <FIELD1>5</FIELD1> <SEQ> <FIELD2>123</FIELD2> <FIELD3>AS</FIELD3> </SEQ> </SEG2> </OGS11> <NEWSEGMENT> <FIELD1>123</FIELD1> </NEWSEGMENT> <NEWSEG1> <FIELD1>COUNT</FIELD1> </NEWSEG1> </ORDER> </ns0:SUBHEADER> </ns0:HEADER>
期望输出XML
<?xml version="1.0" encoding="UTF-8"?> <ns0:HEADER xmlns:ns0="http://idenity.com"> <ns0:SUBHEADER> <ORDER> <HN> <field1>1233</field1> </HN> <GS1> <field1>1</field1> </GS1> <OGS11> <SEG> <SEQ1>21</SEQ1> <SEQ> <FIELD1>123</FIELD1> <FIELD2>EN</FIELD2> </SEQ> </SEG> <SEG2> <FIELD1>5</FIELD1> <SEQ> <FIELD2>123</FIELD2> <FIELD3>AS</FIELD3> </SEQ> </SEG2> </OGS11> <OGS11> <SEG> <SEQ1>23</SEQ1> <SEQ> <FIELD1>1234</FIELD1> <FIELD2>EN</FIELD2> </SEQ> </SEG> <SEG2> <FIELD1>5</FIELD1> <SEQ> <FIELD2>1414</FIELD2> <FIELD3>AS</FIELD3> </SEQ> </SEG2> </OGS11> <NEWSEGMENT> <FIELD1>123</FIELD1> </NEWSEGMENT> <NEWSEG1> <FIELD1>COUNT</FIELD1> </NEWSEG1> </ORDER> <ORDER> <HN> <field1>1234</field1> </HN> <GS1> <field1>1</field1> </GS1> <OGS11> <SEG> <SEQ1>21</SEQ1> <SEQ> <FIELD1>123</FIELD1> <FIELD2>EN</FIELD2> </SEQ> </SEG> <SEG2> <FIELD1>5</FIELD1> <SEQ> <FIELD2>123</FIELD2> <FIELD3>AS</FIELD3> </SEQ> </SEG2> </OGS11> <NEWSEGMENT> <FIELD1>123</FIELD1> </NEWSEGMENT> <NEWSEG1> <FIELD1>COUNT</FIELD1> </NEWSEG1> </ORDER> </ns0:SUBHEADER> </ns0:HEADER>
原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"> <xsl:template match="*[ORDER/OGS11]"> <xsl:copy> <xsl:apply-templates select="@*, * except OGS11"/> <xsl:for-each-group select="OGS11" composite="yes" group-by="*/*[name() != 'SEQ1']"> <xsl:sequence select="."/> </xsl:for-each-group> </xsl:copy> </xsl:template> <xsl:output method="xml" indent="yes"/> <xsl:mode on-no-match="shallow-copy"/> </xsl:stylesheet>
问题排查与修正
原代码问题点
- 模板匹配范围错误:原模板匹配
*[ORDER/OGS11],会命中SUBHEADER或HEADER这类上层节点,导致OGS11的分组操作不是在单个ORDER节点内执行,而是在整个父节点下跨ORDER分组,不符合需求。 - 分组键表达式不准确:
group-by="*/*[name() != 'SEQ1']"仅选取了OGS11子节点的子节点中排除SEQ1的部分,没有完整覆盖OGS11下所有需要对比的节点结构,导致分组判定逻辑错误。
修正后的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"> <xsl:template match="ORDER"> <xsl:copy> <!-- 复制ORDER下除OGS11外的所有节点 --> <xsl:apply-templates select="@*, node() except OGS11"/> <!-- 在当前ORDER内对OGS11分组,排除SEQ1字段 --> <xsl:for-each-group select="OGS11" composite="yes" group-by="node() except SEG/SEQ1"> <!-- 保留每个分组的第一个OGS11实例 --> <xsl:sequence select="current-group()[1]"/> </xsl:for-each-group> </xsl:copy> </xsl:template> <xsl:output method="xml" indent="yes"/> <xsl:mode on-no-match="shallow-copy"/> </xsl:stylesheet>
修正说明
- 模板精准匹配
ORDER节点,确保每个ORDER内独立处理OGS11的重复项 group-by="node() except SEG/SEQ1":明确排除OGS11/SEG/SEQ1节点,以其余所有节点的结构和内容作为分组依据current-group()[1]:仅保留每个分组中的第一个OGS11实例,删除后续重复项composite="yes":启用复合分组,确保完整对比节点的结构和内容,而非仅字符串值
内容的提问来源于stack exchange,提问作者Pavan
相关产品推荐
相关产品推荐

