非同级元素的XSLT累计求和实现问题
嘿,我懂你现在的困扰!想给OrderAmounts下的cost和pages分别计算累计求和,却只找到同级元素的示例,确实有点摸不着头脑。别慌,咱们一步步来搞定这个问题~
首先先假设你的XML结构大概是这样的(如果和实际有出入,你可以按需调整节点路径):
示例XML结构:
<Orders> <Order> <OrderAmounts> <cost>100</cost> <pages>20</pages> </OrderAmounts> </Order> <Order> <OrderAmounts> <cost>150</cost> <pages>30</pages> </OrderAmounts> </Order> <Order> <OrderAmounts> <cost>80</cost> <pages>15</pages> </OrderAmounts> </Order> </Orders>
方案1:XSLT 1.0 实现累计求和
如果你的环境只能用XSLT 1.0(没有原生累加函数),可以通过preceding-sibling轴选中当前节点之前的所有对应元素,求和后加上当前值来实现累计:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/Orders"> <RunningTotals> <xsl:apply-templates select="Order"/> </RunningTotals> </xsl:template> <xsl:template match="Order"> <Order> <current_cost><xsl:value-of select="OrderAmounts/cost"/></current_cost> <running_total_cost> <!-- 累加当前Order之前所有的cost,再加上当前的cost --> <xsl:value-of select="sum(preceding-sibling::Order/OrderAmounts/cost) + OrderAmounts/cost"/> </running_total_cost> <current_pages><xsl:value-of select="OrderAmounts/pages"/></current_pages> <running_total_pages> <!-- pages的累计逻辑和cost完全一致 --> <xsl:value-of select="sum(preceding-sibling::Order/OrderAmounts/pages) + OrderAmounts/pages"/> </running_total_pages> </Order> </xsl:template> </xsl:stylesheet>
方案2:XSLT 2.0+ 简化实现
如果可以用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="/Orders"> <RunningTotals> <!-- 先把所有Order节点存到变量里,方便后续引用 --> <xsl:variable name="allOrders" select="Order"/> <xsl:for-each select="$allOrders"> <!-- 获取当前节点的位置 --> <xsl:variable name="currentPos" select="position()"/> <Order> <current_cost><xsl:value-of select="OrderAmounts/cost"/></current_cost> <running_total_cost> <!-- 累加第1到当前位置的所有cost --> <xsl:value-of select="sum($allOrders[position() le $currentPos]/OrderAmounts/cost)"/> </running_total_cost> <current_pages><xsl:value-of select="OrderAmounts/pages"/></current_pages> <running_total_pages> <!-- pages的累计逻辑同理 --> <xsl:value-of select="sum($allOrders[position() le $currentPos]/OrderAmounts/pages)"/> </running_total_pages> </Order> </xsl:for-each> </RunningTotals> </xsl:template> </xsl:stylesheet>
最终期望输出示例
运行上面任意一套XSL代码后,你会得到类似这样的累计求和结果:
<RunningTotals> <Order> <current_cost>100</current_cost> <running_total_cost>100</running_total_cost> <current_pages>20</current_pages> <running_total_pages>20</running_total_pages> </Order> <Order> <current_cost>150</current_cost> <running_total_cost>250</running_total_cost> <current_pages>30</current_pages> <running_total_pages>50</running_total_pages> </Order> <Order> <current_cost>80</current_cost> <running_total_cost>330</running_total_cost> <current_pages>15</current_pages> <running_total_pages>65</running_total_pages> </Order> </RunningTotals>
小提示
如果你的XML结构和示例不同(比如OrderAmounts的父节点不是Order),只需要调整XPath里的节点路径即可——核心思路就是:
- 对于XSLT1.0:选中当前节点之前所有包含目标子元素的父节点,求和子元素后加上当前值
- 对于XSLT2.0+:选中当前及之前的所有父节点,直接求和它们的目标子元素
内容的提问来源于stack exchange,提问作者AJG
相关产品推荐
相关产品推荐

