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

如何通过XSLT基于节点ID合并XML节点,生成正确item嵌套结构?

解决XML中按ID匹配嵌套orderList节点的XSLT方案

先给出符合需求的示例输入XML结构:

<root>
  <customers>
    <customer id="1">
      <name>Alice</name>
      <position></position>
    </customer>
    <customer id="2">
      <name>Bob</name>
      <position></position>
    </customer>
  </customers>
  <orderList>
    <order id="1">
      <position>
        <price>100</price>
        <currency>USD</currency>
      </position>
      <position>
        <price>200</price>
        <currency>EUR</currency>
      </position>
    </order>
    <order id="2">
      <position>
        <price>150</price>
        <currency>GBP</currency>
      </position>
    </order>
  </orderList>
</root>

下面是实现需求的XSLT代码(基于XSLT 1.0,兼容性覆盖绝大多数XML处理器):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- 按order的id建立position节点的索引,用于快速匹配 -->
  <xsl:key name="order-positions" match="orderList/order/position" use="../@id"/>

  <!-- 通用模板:原样复制所有未特殊处理的节点,保留原有XML结构 -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- 处理customer下的position节点,插入对应id的order position作为独立item -->
  <xsl:template match="customer/position">
    <xsl:copy>
      <!-- 通过key快速获取当前customer对应id的所有order position -->
      <xsl:apply-templates select="key('order-positions', ../@id)">
        <xsl:with-param name="wrap-tag" select="'item'"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <!-- 将每个position节点包装为指定的item标签 -->
  <xsl:template match="position">
    <xsl:param name="wrap-tag"/>
    <xsl:element name="{$wrap-tag}">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

代码逻辑说明

  1. 索引定义:用<xsl:key>建立order的id与下属position节点的映射,比直接路径查询更高效,适合处理大体积XML。
  2. 通用模板:保证除了需要修改的部分,XML中所有节点(属性、文本、其他元素)都原样复制,避免丢失原有内容。
  3. customer节点处理:匹配每个customer下的position节点,插入对应id的所有order position,且每个position都被包装为独立的<item>节点。
  4. 标签包装:通过参数传递包装标签名,后续若需修改标签名称,只需调整参数值即可,提升模板灵活性。

输出结果示例

处理后每个customer的position下会生成独立的item节点,每个item对应一个order里的position:

<root>
  <customers>
    <customer id="1">
      <name>Alice</name>
      <position>
        <item>
          <price>100</price>
          <currency>USD</currency>
        </item>
        <item>
          <price>200</price>
          <currency>EUR</currency>
        </item>
      </position>
    </customer>
    <customer id="2">
      <name>Bob</name>
      <position>
        <item>
          <price>150</price>
          <currency>GBP</currency>
        </item>
      </position>
    </customer>
  </customers>
  <orderList>
    <order id="1">
      <position>
        <price>100</price>
        <currency>USD</currency>
      </position>
      <position>
        <price>200</price>
        <currency>EUR</currency>
      </position>
    </order>
    <order id="2">
      <position>
        <price>150</price>
        <currency>GBP</currency>
      </position>
    </order>
  </orderList>
</root>

可选优化

如果不需要保留原有的orderList节点,只需添加以下模板让它不输出:

<xsl:template match="orderList"/>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 10:05:56