如何使用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
相关产品推荐
相关产品推荐

