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

XSLT排序异常:E_E20下非ROOT节点丢失,求修正方案

XSLT排序问题:保留非ROOT节点并按MAT分组排序ROOT节点

需求说明

仅对/HEADER/DOC/E_E20下MAT值相同的ROOT节点,以FIELD3为关键字进行排序,其余节点(如ND2、ND3、L18等)保持原有位置不变。当前编写的XSLT虽能实现排序逻辑,但丢失了E_E20下的非ROOT初始节点。

输入XML

<?xml version="1.0" encoding="UTF-8"?>
<HEADER>
    <DOC BEGIN="1">
        <EDI_40>
            <Field1>123</Field1>
        </EDI_40>
        <E_E20>
            <ND2>123</ND2>
            <ND3>345</ND3>
            <L18 SEGMENT="1">
                <QUALF>PGI</QUALF>
            </L18>
            <ROOT SEGMENT="1">
                <POS>000020</POS>
                <MAT>1234</MAT>
                <FIELD3>4199</FIELD3>
                <QUAN>3420</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000010</POS>
                <MAT>123456</MAT>
                <FIELD3>4199BI015</FIELD3>
                <QUAN>3420</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN1</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000010</POS>
                <MAT>123456</MAT>
                <FIELD3>4184AI015</FIELD3>
                <QUAN>1026</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN2</PQ>
                </CHILD>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN2</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000010</POS>
                <MAT>123456</MAT>
                <FIELD3>4200AI015</FIELD3>
                <QUAN>1197</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN3</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000030</POS>
                <MAT>123</MAT>
                <FIELD3>4200AI</FIELD3>
                <QUAN>1197</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN</PQ>
                </CHILD>
            </ROOT>
        </E_E20>
    </DOC>
</HEADER>

期望输出XML

<?xml version="1.0" encoding="UTF-8"?>
<HEADER>
    <DOC BEGIN="1">
        <EDI_40>
            <Field1>123</Field1>
        </EDI_40>
        <E_E20>
            <ND2>123</ND2>
            <ND3>345</ND3>
            <L18 SEGMENT="1">
                <QUALF>PGI</QUALF>
            </L18>
            <ROOT SEGMENT="1">
                <POS>000020</POS>
                <MAT>1234</MAT>
                <FIELD3>4199</FIELD3>
                <QUAN>3420</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000010</POS>
                <MAT>123456</MAT>
                <FIELD3>4184AI015</FIELD3>
                <QUAN>1026</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN2</PQ>
                </CHILD>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN2</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000010</POS>
                <MAT>123456</MAT>
                <FIELD3>4199BI015</FIELD3>
                <QUAN>3420</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN1</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000010</POS>
                <MAT>123456</MAT>
                <FIELD3>4200AI015</FIELD3>
                <QUAN>1197</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN3</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000030</POS>
                <MAT>123</MAT>
                <FIELD3>4200AI</FIELD3>
                <QUAN>1197</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN</PQ>
                </CHILD>
            </ROOT>
        </E_E20>
    </DOC>
</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"
  expand-text="yes">

  <xsl:output method="xml" indent="yes"/>

  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:template match="E_E20">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each-group select="ROOT" group-by="MAT">
        <xsl:apply-templates select="current-group()">
          <xsl:sort select="FIELD3"/>
        </xsl:apply-templates>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

问题原因及解决方案

问题原因

原模板仅处理了E_E20下的ROOT节点,完全忽略了其他子节点(如ND2、ND3、L18),导致这些节点在输出中丢失。

修正后的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">

  <xsl:output method="xml" indent="yes"/>

  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:template match="E_E20">
    <xsl:copy>
      <xsl:apply-templates select="@* | *[not(self::ROOT)]"/>
      <!-- 先处理所有非ROOT节点,保留原有位置 -->
      <xsl:for-each-group select="ROOT" group-by="MAT">
        <xsl:apply-templates select="current-group()">
          <xsl:sort select="FIELD3"/>
        </xsl:apply-templates>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

说明

修正后的模板在处理E_E20时,先通过@* | *[not(self::ROOT)]处理所有属性和非ROOT子节点,确保这些节点保留原位置;然后再对ROOT节点按MAT分组,并在每组内按FIELD3排序输出,既满足排序需求,又保留了其他节点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 04:48:08