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

如何使用XSLT在分组的每一行显示小计

如何在每个分组行中显示小计金额?

需求:按Supplier_Invoice_Number对Report_Entry分组,给每个条目添加对应分组的SubTotal字段(即同发票号下所有Amount的总和)。现有代码仅显示当前条目的Amount值,无法得到分组小计,求解决方法。

输入示例

<Report_Data>
    <Report_Entry>
        <Supplier_Invoice_Number>SINV-01</Supplier_Invoice_Number>
        <Supplier_Invoice_Line>1</Supplier_Invoice_Line>
        <Memo>SC0590</Memo>
        <Amount>10</Amount>
    </Report_Entry>
    <Report_Entry>
        <Supplier_Invoice_Number>SINV-01</Supplier_Invoice_Number>
        <Supplier_Invoice_Line>2</Supplier_Invoice_Line>
        <Memo>SC0590</Memo>
        <Amount>-100</Amount>
    </Report_Entry>
    <Report_Entry>
        <Supplier_Invoice_Number>SINV-02</Supplier_Invoice_Number>
        <Supplier_Invoice_Line>1</Supplier_Invoice_Line>
        <Memo>SC0590</Memo>
        <Amount>10</Amount>
    </Report_Entry>
    <Report_Entry>
        <Supplier_Invoice_Number>SINV-02</Supplier_Invoice_Number>
        <Supplier_Invoice_Line>2</Supplier_Invoice_Line>
        <Memo>SC0590</Memo>
        <Amount>10</Amount>
    </Report_Entry>
</Report_Data>

预期输出

<Report_Data>
    <Report_Entry>
        <Supplier_Invoice_Number>SINV-01</Supplier_Invoice_Number>
        <Supplier_Invoice_Line>1</Supplier_Invoice_Line>
        <Memo>SC0590</Memo>
        <Amount>10</Amount>
        <SubTotal>-90</SubTotal>
    </Report_Entry>
    <Report_Entry>
        <Supplier_Invoice_Number>SINV-01</Supplier_Invoice_Number>
        <Supplier_Invoice_Line>2</Supplier_Invoice_Line>
        <Memo>SC0590</Memo>
        <Amount>-100</Amount>
        <SubTotal>-90</SubTotal>
    </Report_Entry>
    <Report_Entry>
        <Supplier_Invoice_Number>SINV-02</Supplier_Invoice_Number>
        <Supplier_Invoice_Line>1</Supplier_Invoice_Line>
        <Memo>SC0590</Memo>
        <Amount>10</Amount>
        <SubTotal>20</SubTotal>
    </Report_Entry>
    <Report_Entry>
        <Supplier_Invoice_Number>SINV-02</Supplier_Invoice_Number>
        <Supplier_Invoice_Line>2</Supplier_Invoice_Line>
        <Memo>SC0590</Memo>
        <Amount>10</Amount>
        <SubTotal>20</SubTotal>
    </Report_Entry>
</Report_Data>

现有代码(问题所在)

<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 method="xml" indent="yes"/>
        <xsl:template match="Report_Data">
            <Report_Data>
                <xsl:for-each select="Report_Entry">
                    <Report_Entry>
                        <xsl:copy-of select="Supplier_Invoice_Number"/>
                        <xsl:copy-of select="Supplier_Invoice_Line"/>
                        <xsl:copy-of select="Memo"/>
                        <xsl:copy-of select="Amount"/>
                        <SubTotal>
                            <xsl:for-each-group select="." group-by="Supplier_Invoice_Number">
                            <xsl:value-of select="sum(Amount)"/>
                            </xsl:for-each-group>
                        </SubTotal>
                    </Report_Entry>
                </xsl:for-each>
            </Report_Data>
            
        </xsl:template>
        
    </xsl:stylesheet>

问题分析

现有代码的核心错误:在遍历单个Report_Entry时,使用xsl:for-each-group select="."仅选择了当前条目本身,分组范围仅包含当前节点,因此sum(Amount)计算的是当前条目的金额,而非整个发票号分组的总和。


解决方案

方法1:使用xsl:key分组查询

通过定义键来快速定位同发票号的所有条目,计算总和:

<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 method="xml" indent="yes"/>
        
        <!-- 定义键,按发票号分组所有条目 -->
        <xsl:key name="invoiceGroup" match="Report_Entry" use="Supplier_Invoice_Number"/>

        <xsl:template match="Report_Data">
            <Report_Data>
                <xsl:for-each select="Report_Entry">
                    <Report_Entry>
                        <!-- 复制所有原有字段,简化代码 -->
                        <xsl:copy-of select="*"/>
                        <SubTotal>
                            <!-- 通过键找到同发票号的所有条目,求和Amount -->
                            <xsl:value-of select="sum(key('invoiceGroup', Supplier_Invoice_Number)/Amount)"/>
                        </SubTotal>
                    </Report_Entry>
                </xsl:for-each>
            </Report_Data>
        </xsl:template>
</xsl:stylesheet>

方法2:预计算分组总和再引用

先一次性计算所有发票号的小计,存储到变量中,遍历条目时直接引用对应值:

<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 method="xml" indent="yes"/>

        <xsl:template match="Report_Data">
            <!-- 预计算每个发票号的总和,存储到变量 -->
            <xsl:variable name="invoiceTotals">
                <xsl:for-each-group select="Report_Entry" group-by="Supplier_Invoice_Number">
                    <Total invoiceNumber="{current-grouping-key()}">
                        <xsl:value-of select="sum(current-group()/Amount)"/>
                    </Total>
                </xsl:for-each-group>
            </xsl:variable>

            <Report_Data>
                <xsl:for-each select="Report_Entry">
                    <Report_Entry>
                        <xsl:copy-of select="*"/>
                        <SubTotal>
                            <!-- 从预计算的变量中获取对应发票号的总和 -->
                            <xsl:value-of select="$invoiceTotals/Total[@invoiceNumber = current()/Supplier_Invoice_Number]"/>
                        </SubTotal>
                    </Report_Entry>
                </xsl:for-each>
            </Report_Data>
        </xsl:template>
</xsl:stylesheet>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 05:45:54