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

如何使用XSLT基于元素进行合并?附输入XML示例

Merging userFee Elements by owner/Id with XSLT

Great question! To merge your userFee elements based on the owner/Id and sum their corresponding Amount/sum values, you can leverage XSLT's grouping features. Below are solutions for both XSLT 2.0+ (the most straightforward approach) and XSLT 1.0 (for compatibility with older processors).


First, Let's Complete Your Input XML

For clarity, here's the full input we'll work with:

<Fees> 
  <user> 
    <value>userA</value> 
  </user> 
  <feeList> 
    <userFee> 
      <owner> 
        <Id>owner1</Id> 
      </owner> 
      <Amount> 
        <sum>100</sum> 
      </Amount> 
    </userFee> 
    <userFee> 
      <owner> 
        <Id>owner1</Id> 
      </owner> 
      <Amount> 
        <sum>100</sum> 
      </Amount> 
    </userFee> 
    <userFee> 
      <owner> 
        <Id>owner2</Id> 
      </owner> 
      <Amount>
        <sum>50</sum>
      </Amount>
    </userFee>
  </feeList>
</Fees>

Solution 1: XSLT 2.0+ (Using xsl:for-each-group)

This version uses native grouping syntax which is clean and easy to read:

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

  <!-- Identity Template: Copies all elements/attributes unless overridden -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- Override processing for `feeList` to group `userFee` elements -->
  <xsl:template match="feeList">
    <xsl:copy>
      <!-- Group `userFee` by the value of `owner/Id` -->
      <xsl:for-each-group select="userFee" group-by="owner/Id">
        <userFee>
          <!-- Copy the `owner` element from the first item in the group (all are identical) -->
          <xsl:apply-templates select="current-group()[1]/owner"/>
          <Amount>
            <!-- Sum all `sum` values in the current group -->
            <sum><xsl:value-of select="sum(current-group()/Amount/sum)"/></sum>
          </Amount>
        </userFee>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Output XML:

<Fees>
  <user>
    <value>userA</value>
  </user>
  <feeList>
    <userFee>
      <owner>
        <Id>owner1</Id>
      </owner>
      <Amount>
        <sum>200</sum>
      </Amount>
    </userFee>
    <userFee>
      <owner>
        <Id>owner2</Id>
      </owner>
      <Amount>
        <sum>50</sum>
      </Amount>
    </userFee>
  </feeList>
</Fees>

Key Explanations:

  • The identity template ensures all parts of the XML (like the user element) are copied exactly as-is unless we specify otherwise.
  • xsl:for-each-group groups userFee elements by their owner/Id value.
  • current-group() refers to all userFee elements in the current group, so sum(current-group()/Amount/sum) calculates the total for that owner.

Solution 2: XSLT 1.0 (Muenchian Grouping)

If you're restricted to XSLT 1.0, use Muenchian grouping (a standard technique for grouping in older versions):

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

  <!-- Define a key to group `userFee` elements by `owner/Id` -->
  <xsl:key name="userFeeByOwnerId" match="userFee" use="owner/Id"/>

  <!-- Identity Template -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- Process `feeList` to select only the first `userFee` in each group -->
  <xsl:template match="feeList">
    <xsl:copy>
      <xsl:apply-templates select="userFee[generate-id() = generate-id(key('userFeeByOwnerId', owner/Id)[1])]"/>
    </xsl:copy>
  </xsl:template>

  <!-- Process each grouped `userFee` to calculate the total sum -->
  <xsl:template match="userFee">
    <userFee>
      <xsl:apply-templates select="owner"/>
      <Amount>
        <sum>
          <!-- Sum all `sum` elements in the group defined by the key -->
          <xsl:value-of select="sum(key('userFeeByOwnerId', owner/Id)/Amount/sum)"/>
        </sum>
      </Amount>
    </userFee>
  </xsl:template>
</xsl:stylesheet>

Key Explanations:

  • The xsl:key creates an index of userFee elements mapped to their owner/Id values.
  • The condition generate-id() = generate-id(key('userFeeByOwnerId', owner/Id)[1]) selects only the first userFee in each group (since all elements in the same group share the same generated ID for their first element).
  • key('userFeeByOwnerId', owner/Id) retrieves all userFee elements for the current owner, allowing us to sum their sum values.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:54:26