首页 > 解决方案 > 使用 XSLT 对 XML 记录进行排序

问题描述

我有以下结构,我只需要根据其中的字段 ECI13 对 ECI 节点进行排序。

<?xml version="1.0" encoding="UTF-8"?>
<ns1:MT_test1 xmlns:ns1="https://www.xxxx.com/Import">
    <PRE>
        <ID>PRE</ID>
        <PRE01>LOAD</PRE01>
    </PRE>
    <MFT>
        <ID>MFT</ID>
        <MFT01>10000000822020</MFT01>
    </MFT>
    <REF>
        <ID>REF</ID>
        <REF01>10000000822020</REF01>
        <REF02>001</REF02>
    </REF>
    <REF>
        <ID>REF</ID>
        <REF01>10000000822020</REF01>
        <REF02>002</REF02>
    </REF>
    <REF>
        <ID>REF</ID>
        <REF01>10000000822020</REF01>
        <REF02>003</REF02>
    </REF>
    <REF>
        <ID>REF</ID>
        <REF01>10000000822020</REF01>
        <REF02>004</REF02>
    </REF>
    <DTM>
        <ID>DTM</ID>
        <DTM01>10000000822020</DTM01>
    </DTM>  
    <EH1>
        <ID>EH1</ID>
        <EH101>10000000822020</EH101>
    </EH1>  
    <ECI>
        <ID>ECI</ID>
        <ECI01>10000000822020</ECI01>
        <ECI02>001</ECI02>
        <ECI13>INV4500000044</ECI13>
    </ECI>
    <ECI>
        <ID>ECI</ID>
        <ECI01>10000000822020</ECI01>
        <ECI02>002</ECI02>
        <ECI13>INV4500000043</ECI13>
    </ECI>
    <ECI>
        <ID>ECI</ID>
        <ECI01>10000000822020</ECI01>
        <ECI02>003</ECI02>
        <ECI13>INV4500000042</ECI13>
    </ECI>
    <END>
        <ID>END</ID>
        <END01/>
    </END>
</ns1:MT_test1>

预期产出

<?xml version="1.0" encoding="UTF-8"?>
<ns1:MT_test1 xmlns:ns1="https://www.xxxx.com/Import">
    <PRE>
        <ID>PRE</ID>
        <PRE01>LOAD</PRE01>
    </PRE>
    <MFT>
        <ID>MFT</ID>
        <MFT01>10000000822020</MFT01>
    </MFT>
    <REF>
        <ID>REF</ID>
        <REF01>10000000822020</REF01>
        <REF02>001</REF02>
    </REF>
    <REF>
        <ID>REF</ID>
        <REF01>10000000822020</REF01>
        <REF02>002</REF02>
    </REF>
    <REF>
        <ID>REF</ID>
        <REF01>10000000822020</REF01>
        <REF02>003</REF02>
    </REF>
    <REF>
        <ID>REF</ID>
        <REF01>10000000822020</REF01>
        <REF02>004</REF02>
    </REF>
    <DTM>
        <ID>DTM</ID>
        <DTM01>10000000822020</DTM01>
    </DTM>
    <EH1>
        <ID>EH1</ID>
        <EH101>10000000822020</EH101>
    </EH1>
    <ECI>
        <ID>ECI</ID>
        <ECI01>10000000822020</ECI01>
        <ECI02>003</ECI02>
        <ECI13>INV4500000042</ECI13>
    </ECI>
    <ECI>
        <ID>ECI</ID>
        <ECI01>10000000822020</ECI01>
        <ECI02>002</ECI02>
        <ECI13>INV4500000043</ECI13>
    </ECI>
    <ECI>
        <ID>ECI</ID>
        <ECI01>10000000822020</ECI01>
        <ECI02>001</ECI02>
        <ECI13>INV4500000044</ECI13>
    </ECI>
    <END>
        <ID>END</ID>
        <END01/>
    </END>
</ns1:MT_test1>

我使用下面的 XSL 代码进行排序。输出只给我 ECI 记录(排序),而不是完整的有效负载。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="https://www.xxxx.com/Import">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="ns1:MT_test1">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <xsl:apply-templates select="ECI">
                <xsl:sort select="ECI13" order="ascending"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

下面是带有上述 xsl 代码的输出(缺少其他节点)。任何帮助将不胜感激。

<?xml version="1.0" encoding="UTF-8"?>
<ns1:MT_test1 xmlns:ns1="https://www.xxxx.com/Import">
    <ECI>
        <ID>ECI</ID>
        <ECI01>10000000822020</ECI01>
        <ECI02>003</ECI02>
        <ECI13>INV4500000042</ECI13>
    </ECI>
    <ECI>
        <ID>ECI</ID>
        <ECI01>10000000822020</ECI01>
        <ECI02>002</ECI02>
        <ECI13>INV4500000043</ECI13>
    </ECI>
    <ECI>
        <ID>ECI</ID>
        <ECI01>10000000822020</ECI01>
        <ECI02>001</ECI02>
        <ECI13>INV4500000044</ECI13>
    </ECI>
</ns1:MT_test1>

谢谢!!SM

标签: xmlxsltxslt-1.0xslt-2.0

解决方案


一种方法是

  <xsl:template match="/*">
      <xsl:copy>
          <xsl:apply-templates select="@*"/>
          <xsl:for-each-group select="*" group-adjacent="boolean(self::ECI)">
              <xsl:apply-templates select="current-group()">
                  <xsl:sort select="if (current-grouping-key()) then ECI13 else position()"/>
              </xsl:apply-templates>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

https://xsltfiddle.liberty-development.net/jxDiMCg

它假设 ECI 元素是相邻的兄弟姐妹。


推荐阅读