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

如何基于XML中兄弟节点的唯一ID值对amt节点求和?

问题:基于XML唯一ID分组求和

我需要按data1元素对XML条目分组,再对每个分组内唯一id对应的amt节点求和,而非直接对所有amt值去重求和。目前的XSLT仅对amt的唯一值求和,未考虑id的唯一性,导致结果错误。


输入XML

<?xml version="1.0" encoding="UTF-8"?>
<Records>
    <Entry>
        <Result>
            <id>123</id>
            <amt>80.00</amt>
        </Result>
        <data1>KEY</data1>
        <data2/>
        <data3/>
        <dataN/>
    </Entry>
    <Entry>
        <Result>
            <id>123</id>
            <amt>80.00</amt>
        </Result>
        <data1>KEY</data1>
        <data2/>
        <data3/>
        <dataN/>
    </Entry>
    <Entry>
        <Result>
            <id>123</id>
            <amt>80</amt>
        </Result>
        <data1>KEY1</data1>
        <data2/>
        <data3/>
        <dataN/>
    </Entry>
    <Entry>
        <Result>
            <id>ABC</id>
            <amt>120.25</amt>
        </Result>
        <data1>KEY</data1>
        <data2/>
        <data3/>
        <dataN/>
    </Entry>
    <Entry>
        <Result>
            <id>ABC</id>
            <amt>120.25</amt>
        </Result>
        <data1>KEY</data1>
        <data2/>
        <data3/>
        <dataN/>
    </Entry>
    <Entry>
        <Result>
            <id>ABC</id>
            <amt>120.25</amt>
        </Result>
        <data1>KEY</data1>
        <data2/>
        <data3/>
        <dataN/>
    </Entry>
    <Entry>
        <Result>
            <id>ABC</id>
            <amt>120.25</amt>
        </Result>
        <data1>KEY</data1>
        <data2/>
        <data3/>
        <dataN/>
    </Entry>
    <Entry>
        <Result>
            <id>AB90</id>
            <amt>75.00</amt>
        </Result>
        <data1>KEY2</data1>
        <data2/>
        <data3/>
        <dataN/>
    </Entry>
    <Entry>
        <Result>
            <id>AB90</id>
            <amt>75.00</amt>
        </Result>
        <data1>KEY2</data1>
        <data2/>
        <data3/>
        <dataN/>
    </Entry>
    <Entry>
        <Result>
            <id>XYZ</id>
            <amt>75.00</amt>
        </Result>
        <data1>KEY2</data1>
        <data2/>
        <data3/>
        <dataN/>
    </Entry>
</Records>

期望输出XML

<?xml version="1.0" encoding="UTF-8"?>
<Records>
    <Entry>
        <amt>200.25</amt>
        <relatedData>
            <data1>KEY</data1>
            <data2/>
            <data3/>
            <dataN/>
        </relatedData>
    </Entry>
    <Entry>
      <amt>80</amt>
      <relatedData>
         <data1>KEY1</data1>
         <data2/>
         <data3/>
         <dataN/>
      </relatedData>
   </Entry>
    <Entry>
        <amt>150.00</amt>
        <relatedData>
            <data1>KEY2</data1>
            <data2/>
            <data3/>
            <dataN/>
        </relatedData>
    </Entry>
</Records>

当前错误的XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">

    <xsl:output indent="yes"/>
    <xsl:template match="Records">

        <root>
            <xsl:for-each-group select="Entry" group-by="data1">
                <Entry>
                    <!-- Sum just amounts from unique entry IDs -->
                    <!-- Doesn't account for unique entry IDs -->
                    <amt>
                        <xsl:value-of select="sum(distinct-values(current-group()/Result/amt))"/>
                    </amt>

                    <!-- output related data -->
                    <relatedData>
                        <data1>
                            <xsl:value-of select="data1"/>
                        </data1>
                        <!-- Place holder code
                        <data2>
                            <xsl:value-of select='sum(current-group()/data2)'/>
                        </data2>
                        <data3>
                            <xsl:value-of select='sum(current-group()/data3)'/>
                        </data3>
                        -->
                    </relatedData>
                </Entry>
            </xsl:for-each-group>
        </root>
    </xsl:template>
</xsl:stylesheet>

当前错误输出

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <Entry>
      <amt>200.25</amt>
      <relatedData>
         <data1>KEY</data1>
      </relatedData>
   </Entry>
   <Entry>
      <amt>80</amt>
      <relatedData>
         <data1>KEY1</data1>
      </relatedData>
   </Entry>
   <Entry>
      <!-- incorrect total, should be 150 -->
      <amt>75</amt>
      <relatedData>
         <data1>KEY2</data1>
      </relatedData>
   </Entry>
</root>

解决方案

问题出在原XSLT仅对amt值去重求和,忽略了不同id可能对应相同amt的情况(比如KEY2分组里的AB90和XYZ,amt都是75.00,但属于不同id,需要各算一次)。

修改后的XSLT需要在每个data1分组内,先按Result/id做二次分组,然后取每个id分组对应的amt值(同一个id的amt值一致),再对这些值求和:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">

    <xsl:output indent="yes"/>
    <xsl:template match="Records">
        <Records>
            <xsl:for-each-group select="Entry" group-by="data1">
                <Entry>
                    <!-- 先按id分组,取每个唯一id对应的amt,再求和 -->
                    <amt>
                        <xsl:value-of select="sum(
                            for $group in current-group()/Result group by $group/id
                            return xs:decimal($group/amt)[1]
                        )"/>
                    </amt>
                    <!-- 输出相关数据,取当前分组第一个Entry的data2、data3等 -->
                    <relatedData>
                        <data1>
                            <xsl:value-of select="data1"/>
                        </data1>
                        <data2>
                            <xsl:value-of select="current-group()[1]/data2"/>
                        </data2>
                        <data3>
                            <xsl:value-of select="current-group()[1]/data3"/>
                        </data3>
                        <dataN>
                            <xsl:value-of select="current-group()[1]/dataN"/>
                        </dataN>
                    </relatedData>
                </Entry>
            </xsl:for-each-group>
        </Records>
    </xsl:template>
</xsl:stylesheet>

说明

  1. 内层通过for $group in current-group()/Result group by $group/id实现对每个data1分组内的id去重;
  2. 每个唯一id对应的amt取第一个值(因为输入里同一id的amt都是相同的),转换为xs:decimal避免字符串求和问题;
  3. 对这些去重后的amt值求和,得到正确结果;
  4. relatedData里的data2、data3等取当前data1分组第一个Entry的对应节点,符合期望输出格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 17:08:11