XSLT 1.0嵌套分组中实现数值求和的技术问题
XSLT 1.0嵌套分组+求和解决方案
针对你按COL[8]、COL[14]、COL[10]、COL[11]嵌套分组并对Price、Tax、Amount求和的需求,用Muenchian分组(XSLT1.0标准分组方法)就能解决,核心是为每个层级的分组定义唯一键,再对分组内的节点集合求和。
示例XML结构
假设你的XML数据结构如下(如果实际结构不同,调整XPath即可):
<Rows> <Row> <COL index="8">AccountA</COL> <COL index="14">CategoryX</COL> <COL index="10">Product1</COL> <COL index="11">SizeM</COL> <COL index="price">100</COL> <COL index="tax">10</COL> <COL index="amount">110</COL> </Row> <Row> <COL index="8">AccountA</COL> <COL index="14">CategoryX</COL> <COL index="10">Product1</COL> <COL index="11">SizeM</COL> <COL index="price">200</COL> <COL index="tax">20</COL> <COL index="amount">220</COL> </Row> <Row> <COL index="8">AccountB</COL> <COL index="14">CategoryY</COL> <COL index="10">Product2</COL> <COL index="11">SizeL</COL> <COL index="price">150</COL> <COL index="tax">15</COL> <COL index="amount">165</COL> </Row> </Rows>
完整XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义各层级分组的键,用|分隔字段避免冲突 --> <xsl:key name="group-col8" match="Row" use="COL[@index='8']"/> <xsl:key name="group-col8-col14" match="Row" use="concat(COL[@index='8'], '|', COL[@index='14'])"/> <xsl:key name="group-col8-col14-col10" match="Row" use="concat(COL[@index='8'], '|', COL[@index='14'], '|', COL[@index='10'])"/> <xsl:key name="group-all" match="Row" use="concat(COL[@index='8'], '|', COL[@index='14'], '|', COL[@index='10'], '|', COL[@index='11'])"/> <xsl:template match="/"> <html> <body> <table border="1"> <!-- 表头 --> <tr> <th>COL8</th> <th>COL14</th> <th>COL10</th> <th>COL11</th> <th>Total Price</th> <th>Total Tax</th> <th>Total Amount</th> </tr> <!-- 第一层分组:COL[8] --> <xsl:for-each select="Rows/Row[generate-id() = generate-id(key('group-col8', COL[@index='8'])[1])]"> <xsl:variable name="col8-val" select="COL[@index='8']"/> <!-- 第二层分组:COL[8]+COL[14] --> <xsl:for-each select="key('group-col8', $col8-val)[generate-id() = generate-id(key('group-col8-col14', concat($col8-val, '|', COL[@index='14']))[1])]"> <xsl:variable name="col14-val" select="COL[@index='14']"/> <!-- 第三层分组:COL[8]+COL[14]+COL[10] --> <xsl:for-each select="key('group-col8-col14', concat($col8-val, '|', $col14-val))[generate-id() = generate-id(key('group-col8-col14-col10', concat($col8-val, '|', $col14-val, '|', COL[@index='10']))[1])]"> <xsl:variable name="col10-val" select="COL[@index='10']"/> <!-- 第四层分组:四个字段组合 --> <xsl:for-each select="key('group-col8-col14-col10', concat($col8-val, '|', $col14-val, '|', $col10-val))[generate-id() = generate-id(key('group-all', concat($col8-val, '|', $col14-val, '|', $col10-val, '|', COL[@index='11']))[1])]"> <!-- 获取当前分组下的所有Row节点 --> <xsl:variable name="current-group" select="key('group-all', concat($col8-val, '|', $col14-val, '|', $col10-val, '|', COL[@index='11']))"/> <tr> <td><xsl:value-of select="$col8-val"/></td> <td><xsl:value-of select="$col14-val"/></td> <td><xsl:value-of select="$col10-val"/></td> <td><xsl:value-of select="COL[@index='11']"/></td> <!-- 对分组内的数值列求和 --> <td><xsl:value-of select="sum($current-group/COL[@index='price'])"/></td> <td><xsl:value-of select="sum($current-group/COL[@index='tax'])"/></td> <td><xsl:value-of select="sum($current-group/COL[@index='amount'])"/></td> </tr> </xsl:for-each> </xsl:for-each> </xsl:for-each> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>
关键说明
- Muenchian分组逻辑:通过
generate-id() = generate-id(key(...)判断当前节点是否是分组的第一个节点,确保每个分组只处理一次。 - 分组键的唯一性:用
concat()拼接多个字段值,并加入分隔符|,避免不同字段组合产生重复键。 - 求和实现:在最内层分组中,先通过分组键获取当前分组的所有节点集合
$current-group,再用sum()函数对集合内的对应数值列求和。 - 适配调整:如果你的XML中COL的属性不是
@index,或者数值列的索引/名称不同,直接修改XPath表达式即可。如果需要添加更高层级的合计(比如COL[8]级别的总求和),在对应分组层级中对key('group-col8', $col8-val)节点集合求和即可。
内容的提问来源于stack exchange,提问作者Javier Bosque
相关产品推荐
相关产品推荐

