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

XSLT实现XML ID去重并动态添加元素的技术问题

解决XSLT按ID分组并关联price和country的问题

嘿,看来你卡在XSLT分组关联数据这一步了!别担心,这是处理重复节点时很常见的需求,我给你两种解决方案,分别适配不同版本的XSLT,帮你把带重复ID的data节点按ID分组,同时正确关联对应的price和country元素。


先明确你的需求场景(示例)

假设你的源XML是这样的:

<root>
  <data>
    <id>1</id>
    <price>10.99</price>
    <country>US</country>
  </data>
  <data>
    <id>1</id>
    <price>12.99</price>
    <country>CA</country>
  </data>
  <data>
    <id>2</id>
    <price>15.99</price>
    <country>UK</country>
  </data>
</root>

你期望的目标XML结构:

<Products>
  <Product>
    <id>1</id>
    <prices>
      <price country="US">10.99</price>
      <price country="CA">12.99</price>
    </prices>
  </Product>
  <Product>
    <id>2</id>
    <prices>
      <price country="UK">15.99</price>
    </prices>
  </Product>
</Products>

方案1:XSLT 1.0(Muenchian分组法)

XSLT 1.0没有原生的分组语法,所以经典的解决方案是用Muenchian分组,通过定义键来实现分组:

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

  <!-- 定义键:按data节点的id值分组 -->
  <xsl:key name="data-by-id" match="data" use="id"/>

  <xsl:template match="/root">
    <Products>
      <!-- 筛选出每个ID组的第一个节点(即去重后的唯一ID) -->
      <xsl:for-each select="data[count(. | key('data-by-id', id)[1]) = 1]">
        <Product>
          <id><xsl:value-of select="id"/></id>
          <prices>
            <!-- 遍历当前ID对应的所有data节点,获取price和country -->
            <xsl:for-each select="key('data-by-id', id)">
              <price country="{country}">
                <xsl:value-of select="price"/>
              </price>
            </xsl:for-each>
          </prices>
        </Product>
      </xsl:for-each>
    </Products>
  </xsl:template>
</xsl:stylesheet>

关键逻辑解释:

  • <xsl:key>:创建一个名为data-by-id的键,匹配所有data节点,以id的值作为分组依据。
  • data[count(. | key('data-by-id', id)[1]) = 1]:这个表达式用来筛选每个分组的第一个节点(也就是去重后的唯一ID),确保每个ID只处理一次。
  • key('data-by-id', id):通过当前ID,获取该分组下的所有data节点,这样就能拿到对应的price和country了。

方案2:XSLT 2.0+(原生分组语法)

如果你的环境支持XSLT 2.0及以上版本,那可以直接用原生的<xsl:for-each-group>语法,代码更简洁易懂:

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

  <xsl:template match="/root">
    <Products>
      <!-- 按data节点的id值分组 -->
      <xsl:for-each-group select="data" group-by="id">
        <Product>
          <!-- 获取当前分组的ID值 -->
          <id><xsl:value-of select="current-grouping-key()"/></id>
          <prices>
            <!-- 遍历当前分组下的所有data节点 -->
            <xsl:for-each select="current-group()">
              <price country="{country}">
                <xsl:value-of select="price"/>
              </price>
            </xsl:for-each>
          </prices>
        </Product>
      </xsl:for-each-group>
    </Products>
  </xsl:template>
</xsl:stylesheet>

关键逻辑解释:

  • <xsl:for-each-group select="data" group-by="id">:直接指定按id对data节点分组。
  • current-grouping-key():返回当前分组的键值(也就是当前的ID)。
  • current-group():返回当前分组下的所有data节点,轻松获取每个节点的price和country。

这两种方案都能完美实现你要的按ID分组并关联对应数据的需求,你可以根据自己的XSLT版本选择合适的代码~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:20:17