基于XSLT 2.0实现多维度分组求和的技术求助
解决方案:XSLT 2.0 多维度分组汇总
问题背景
需在XSLT 2.0环境下,对交易数据按MemberID、DepositDate、DepositType进行三级分组,汇总每个分组的存款金额。此前使用的XSLT 3.0方案因环境限制无法兼容,需改用XSLT 2.0原生语法实现。
XML输入示例
<Transactions> <Transaction> <MemberID>M001</MemberID> <DepositDate>2024-01-01</DepositDate> <DepositType>定期</DepositType> <Amount>1000</Amount> </Transaction> <Transaction> <MemberID>M001</MemberID> <DepositDate>2024-01-01</DepositDate> <DepositType>活期</DepositType> <Amount>500</Amount> </Transaction> <Transaction> <MemberID>M001</MemberID> <DepositDate>2024-01-02</DepositDate> <DepositType>定期</DepositType> <Amount>2000</Amount> </Transaction> <Transaction> <MemberID>M002</MemberID> <DepositDate>2024-01-01</DepositDate> <DepositType>活期</DepositType> <Amount>1500</Amount> </Transaction> </Transactions>
期望输出
<Summary> <MemberSummary MemberID="M001"> <DateSummary DepositDate="2024-01-01"> <TypeSummary DepositType="定期" TotalAmount="1000"/> <TypeSummary DepositType="活期" TotalAmount="500"/> </DateSummary> <DateSummary DepositDate="2024-01-02"> <TypeSummary DepositType="定期" TotalAmount="2000"/> </DateSummary> </MemberSummary> <MemberSummary MemberID="M002"> <DateSummary DepositDate="2024-01-01"> <TypeSummary DepositType="活期" TotalAmount="1500"/> </DateSummary> </MemberSummary> </Summary>
无效XSLT 3.0代码及问题
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/Transactions"> <Summary> <xsl:for-each-group select="Transaction" group-by="concat(MemberID, '|', DepositDate, '|', DepositType)"> <MemberSummary MemberID="{current-grouping-key()[1]}"> <DateSummary DepositDate="{current-grouping-key()[2]}"> <TypeSummary DepositType="{current-grouping-key()[3]}" TotalAmount="{sum(current-group()/Amount)}"/> </DateSummary> </MemberSummary> </xsl:for-each-group> </Summary> </xsl:template> </xsl:stylesheet>
问题:XSLT 2.0不支持current-grouping-key()的数组式访问,且单级分组拼接键值会导致重复生成MemberSummary和DateSummary节点,无法形成层级结构。
正确的XSLT 2.0实现
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/Transactions"> <Summary> <!-- 第一级:按MemberID分组 --> <xsl:for-each-group select="Transaction" group-by="MemberID"> <MemberSummary MemberID="{current-grouping-key()}"> <!-- 第二级:当前会员组内按DepositDate分组 --> <xsl:for-each-group select="current-group()" group-by="DepositDate"> <DateSummary DepositDate="{current-grouping-key()}"> <!-- 第三级:当前日期组内按DepositType分组并汇总金额 --> <xsl:for-each-group select="current-group()" group-by="DepositType"> <TypeSummary DepositType="{current-grouping-key()}" TotalAmount="{sum(current-group()/Amount)}"/> </xsl:for-each-group> </DateSummary> </xsl:for-each-group> </MemberSummary> </xsl:for-each-group> </Summary> </xsl:template> </xsl:stylesheet>
说明:
- 采用嵌套分组方式,依次按
MemberID→DepositDate→DepositType层级分组,完全符合XSLT 2.0语法规范。 - 使用
current-group()获取当前分组内的所有节点,current-grouping-key()获取当前分组的键值。 - 最内层分组通过
sum(current-group()/Amount)计算该分组的总金额。
内容的提问来源于stack exchange,提问作者Wasupbi
相关产品推荐
相关产品推荐

