XSLT为非兄弟姐妹运行总计

时间:2018-02-07 18:42:34

标签: xml xslt

我正在尝试计算XML文档中成本和页面元素的运行总计,如下所示。

鉴于费用和页面都是OrderAmounts的子项,我不知道如何完成运行总计。我搜索了其他答案,但只能找到计算兄弟元素的运行总数的参考。

XML

<Root>
  <Info>
    <CustomerName>Clay Allen</CustomerName>
    <CustAddr>123 Main St</CustAddr>
    <Date>2018-02-07</Date>
  </Info>
  <Details>
    <AdditionalDetails>
      <OrderDetails>
        <Order>
         <OrderNumber>A1</OrderNumber>
         <OrderAmounts>
           <Cost>100</Cost>
           <Pages>1325</Pages>
         </OrderAmounts>
        </Order>
        <Order>
         <OrderNumber>A2</OrderNumber>
         <OrderAmounts>
           <Cost>75</Cost>
           <Pages>950</Pages>
         </OrderAmounts>
        </Order>
      </OrderDetails>
    </AdditionalDetails>
  </Details>
</Root>

我的XSL

<xsl:for-each select="Root/Details/AdditionalDetails/OrderDetails/Order">
  (Cumulative value: <xsl:variable name="temp1" select="sum(preceding-sibling::Order)+OrderAmounts/Cost"/><xsl:value-of select="$temp1"/>)<br/>
  (Cumulative value: <xsl:variable name="temp2" select="sum(preceding-sibling::Order)+OrderAmounts/Pages"/><xsl:value-of select="$temp2"/>)
  <br/><br/>
</xsl:for-each>

产生输出

100
1325

75
950

期望的输出

175
2275

建议表示赞赏。

2 个答案:

答案 0 :(得分:0)

&#39;和()&#39;函数需要任何节点集来评估总数(它们不需要是兄弟姐妹),所以你的问题是找到正确的XPATH来为sum函数选择节点。所以以下内容应该有效。

<TotalCosts>
    <xsl:value-of select="sum(//OrderAmounts/Cost)"/>
</TotalCosts>
<TotalPages>
    <xsl:value-of select="sum(//OrderAmounts/Pages)"/>
</TotalPages>

答案 1 :(得分:0)

简单的答案是,您想要sum(preceding-sibling::Order)+OrderAmounts/Cost而不是sum(preceding-sibling::OrderOrderAmounts/Cost)+OrderAmounts/Cost

但是,这是订单数量的二次方,对于XSLT 3.0,您可以使用xsl:iterate来计算运行总计来改善这一点:

<xsl:iterate select="Order">
  <xsl:param name="cost-so-far" as="xs:decimal" select="0"/>
  <xsl:param name="pages-so-far" as="xs:integer" select="0"/>
  ...
  <xsl:next-iteration>
    <xsl:with-param name="cost-so-far" select="$cost-so-far + xs:decimal(OrderAmounts/Cost)"/> 
    <xsl:with-param name="pages-so-far" select="$pages-so-far + xs:decimal(OrderAmounts/Pages)"/> 
  </xsl:next-iteration>
</xsl:iterate>