如何在XSLT中按TabVatCode分组汇总TabVat表格生成TabSum
XSLT分组汇总实现方案
示例输入XML
假设你的源XML结构如下(包含TabVat表格):
<Root> <Table id="TabVat"> <Row> <TabVatCode>20%</TabVatCode> <TabNetAmount>100.00</TabNetAmount> <TabVatAmount>20.00</TabVatAmount> </Row> <Row> <TabVatCode>20%</TabVatCode> <TabNetAmount>200.00</TabNetAmount> <TabVatAmount>40.00</TabVatAmount> </Row> <Row> <TabVatCode>10%</TabVatCode> <TabNetAmount>150.00</TabNetAmount> <TabVatAmount>15.00</TabVatAmount> </Row> </Table> <OtherContent>保留的其他内容</OtherContent> </Root>
可行的XSLT代码(XSLT 2.0+)
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 复制所有节点和属性,排除TabVat表格 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()[not(self::Table[@id='TabVat'])]"/> </xsl:copy> </xsl:template> <!-- 处理根节点,添加汇总表格TabSum --> <xsl:template match="Root"> <xsl:copy> <xsl:apply-templates select="@*|node()[not(self::Table[@id='TabVat'])]"/> <!-- 生成汇总表格 --> <Table id="TabSum"> <!-- 按TabVatCode分组 --> <xsl:for-each-group select="Table[@id='TabVat']/Row" group-by="TabVatCode"> <Row> <TabVatCode><xsl:value-of select="current-grouping-key()"/></TabVatCode> <!-- 汇总TabNetAmount --> <TotalNetAmount> <xsl:value-of select="sum(current-group()/TabNetAmount)"/> </TotalNetAmount> <!-- 汇总TabVatAmount --> <TotalVatAmount> <xsl:value-of select="sum(current-group()/TabVatAmount)"/> </TotalVatAmount> </Row> </xsl:for-each-group> </Table> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键说明
- 节点复制规则:默认模板复制所有非TabVat的节点,保证原XML其他内容完整保留。
- 分组逻辑:通过
xsl:for-each-group按TabVatCode分组,current-grouping-key()获取当前分组的税码值。 - 汇总计算:用
sum(current-group()/字段名)对分组内的数值字段求和,生成汇总行。 - 新表格生成:在根节点下添加id为
TabSum的表格,包含所有分组后的汇总数据,原TabVat表格因被排除复制实现移除效果。
兼容XSLT 1.0的实现(Muenchian分组)
如果只能使用XSLT 1.0,改用Muenchian分组方式:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义分组键 --> <xsl:key name="vatCodeGroup" match="Table[@id='TabVat']/Row" use="TabVatCode"/> <!-- 复制所有节点和属性,排除TabVat表格 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()[not(self::Table[@id='TabVat'])]"/> </xsl:copy> </xsl:template> <!-- 处理根节点,添加汇总表格 --> <xsl:template match="Root"> <xsl:copy> <xsl:apply-templates select="@*|node()[not(self::Table[@id='TabVat'])]"/> <Table id="TabSum"> <!-- 选取每个分组的第一个节点作为代表 --> <xsl:for-each select="Table[@id='TabVat']/Row[generate-id()=generate-id(key('vatCodeGroup', TabVatCode)[1])]"> <Row> <TabVatCode><xsl:value-of select="TabVatCode"/></TabVatCode> <TotalNetAmount> <xsl:value-of select="sum(key('vatCodeGroup', TabVatCode)/TabNetAmount)"/> </TotalNetAmount> <TotalVatAmount> <xsl:value-of select="sum(key('vatCodeGroup', TabVatCode)/TabVatAmount)"/> </TotalVatAmount> </Row> </xsl:for-each> </Table> </xsl:copy> </xsl:template> </xsl:stylesheet>
内容的提问来源于stack exchange,提问作者Fabs
相关产品推荐
相关产品推荐

