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

XSLT排序后Node/LINE段丢失问题排查及修正请求

修复XSLT中Node/LINE节点丢失问题,同时完成Node/ITEM与Node/LINE的分组排序

问题背景

需要对XML中的两类节点分别排序:

  • Node/ITEM:按LINE/CIDENT/FIER[@TYPE='Key1']/VALUE分组,同组内按LINE/CIDENT/FIER[@TYPE='Key2']/VALUE排序
  • Node/LINE:按CIDENT/FIER[@TYPE='Key1']/VALUE分组,同组内按CIDENT/FIER[@TYPE='Key2']/VALUE排序

现有XSLT仅能正确处理Node/ITEM的排序,但Node/LINE节点会完全丢失。以下是示例输入、期望输出及问题XSLT代码:

输入XML示例

<Root>
  <Node>
    <LINE>
      <CIDENT>
        <FIER TYPE="Key1"><VALUE>A</VALUE></FIER>
        <FIER TYPE="Key2"><VALUE>2</VALUE></FIER>
      </CIDENT>
      <DATA>Line A-2</DATA>
    </LINE>
    <LINE>
      <CIDENT>
        <FIER TYPE="Key1"><VALUE>B</VALUE></FIER>
        <FIER TYPE="Key2"><VALUE>1</VALUE></FIER>
      </CIDENT>
      <DATA>Line B-1</DATA>
    </LINE>
    <ITEM>
      <LINE>
        <CIDENT>
          <FIER TYPE="Key1"><VALUE>A</VALUE></FIER>
          <FIER TYPE="Key2"><VALUE>1</VALUE></FIER>
        </CIDENT>
        <DATA>Item A-1</DATA>
      </LINE>
    </ITEM>
    <ITEM>
      <LINE>
        <CIDENT>
          <FIER TYPE="Key1"><VALUE>A</VALUE></FIER>
          <FIER TYPE="Key2"><VALUE>2</VALUE></FIER>
        </CIDENT>
        <DATA>Item A-2</DATA>
      </LINE>
    </ITEM>
  </Node>
</Root>

期望输出XML示例

<Root>
  <Node>
    <LINE>
      <CIDENT>
        <FIER TYPE="Key1"><VALUE>A</VALUE></FIER>
        <FIER TYPE="Key2"><VALUE>2</VALUE></FIER>
      </CIDENT>
      <DATA>Line A-2</DATA>
    </LINE>
    <LINE>
      <CIDENT>
        <FIER TYPE="Key1"><VALUE>B</VALUE></FIER>
        <FIER TYPE="Key2"><VALUE>1</VALUE></FIER>
      </CIDENT>
      <DATA>Line B-1</DATA>
    </LINE>
    <ITEM>
      <LINE>
        <CIDENT>
          <FIER TYPE="Key1"><VALUE>A</VALUE></FIER>
          <FIER TYPE="Key2"><VALUE>1</VALUE></FIER>
        </CIDENT>
        <DATA>Item A-1</DATA>
      </LINE>
    </ITEM>
    <ITEM>
      <LINE>
        <CIDENT>
          <FIER TYPE="Key1"><VALUE>A</VALUE></FIER>
          <FIER TYPE="Key2"><VALUE>2</VALUE></FIER>
        </CIDENT>
        <DATA>Item A-2</DATA>
      </LINE>
    </ITEM>
  </Node>
</Root>

当前问题XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:key name="itemKey1" match="Node/ITEM" use="LINE/CIDENT/FIER[@TYPE='Key1']/VALUE"/>

  <xsl:template match="/">
    <Root>
      <Node>
        <!-- 仅处理了ITEM节点,完全忽略LINE节点 -->
        <xsl:for-each select="Node/ITEM[generate-id() = generate-id(key('itemKey1', LINE/CIDENT/FIER[@TYPE='Key1']/VALUE)[1])]">
          <xsl:sort select="LINE/CIDENT/FIER[@TYPE='Key1']/VALUE"/>
          <xsl:for-each select="key('itemKey1', LINE/CIDENT/FIER[@TYPE='Key1']/VALUE)">
            <xsl:sort select="LINE/CIDENT/FIER[@TYPE='Key2']/VALUE"/>
            <xsl:copy-of select="."/>
          </xsl:for-each>
        </xsl:for-each>
      </Node>
    </Root>
  </xsl:template>
</xsl:stylesheet>

问题排查

当前XSLT只编写了Node/ITEM的排序逻辑,完全没有处理Node/LINE节点,导致这部分节点在输出中丢失。同时缺少身份模板,无法保留XML的其他原有结构。

修正后的XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <!-- 为ITEM按Key1分组的键 -->
  <xsl:key name="itemKey1" match="Node/ITEM" use="LINE/CIDENT/FIER[@TYPE='Key1']/VALUE"/>
  <!-- 为LINE按Key1分组的键 -->
  <xsl:key name="lineKey1" match="Node/LINE" use="CIDENT/FIER[@TYPE='Key1']/VALUE"/>

  <!-- 身份模板:原样复制未被特殊处理的节点和属性 -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- 专门处理Node节点,分别排序LINE和ITEM -->
  <xsl:template match="Node">
    <xsl:copy>
      <!-- 处理Node/LINE的分组排序 -->
      <xsl:for-each select="LINE[generate-id() = generate-id(key('lineKey1', CIDENT/FIER[@TYPE='Key1']/VALUE)[1])]">
        <xsl:sort select="CIDENT/FIER[@TYPE='Key1']/VALUE"/>
        <xsl:for-each select="key('lineKey1', CIDENT/FIER[@TYPE='Key1']/VALUE)">
          <xsl:sort select="CIDENT/FIER[@TYPE='Key2']/VALUE"/>
          <xsl:copy-of select="."/>
        </xsl:for-each>
      </xsl:for-each>

      <!-- 处理Node/ITEM的分组排序(仅当存在ITEM时执行) -->
      <xsl:if test="ITEM">
        <xsl:for-each select="ITEM[generate-id() = generate-id(key('itemKey1', LINE/CIDENT/FIER[@TYPE='Key1']/VALUE)[1])]">
          <xsl:sort select="LINE/CIDENT/FIER[@TYPE='Key1']/VALUE"/>
          <xsl:for-each select="key('itemKey1', LINE/CIDENT/FIER[@TYPE='Key1']/VALUE)">
            <xsl:sort select="LINE/CIDENT/FIER[@TYPE='Key2']/VALUE"/>
            <xsl:copy-of select="."/>
          </xsl:for-each>
        </xsl:for-each>
      </xsl:if>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

修正说明

  • 添加身份模板:这是XSLT的常规操作,确保XML中除LINE、ITEM外的其他节点和属性都能原样复制,避免结构丢失。
  • 新增LINE分组键:创建lineKey1键,和ITEM的itemKey1对应,实现LINE按Key1分组的逻辑。
  • 重写Node节点处理逻辑:在Node标签内先处理LINE的分组排序,再处理ITEM的排序,保证两类节点都被保留并按规则排序。
  • 添加ITEM存在判断:避免当没有ITEM节点时输出空内容,提升代码严谨性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 20:22:11