如何将xsl的计算结果放在新元素中

时间:2011-07-21 16:31:06

标签: xml xslt

我使用xsl来计算每个元素“Basisproduct”的累计总数。 输出最终放在同一个xml中,在“Totals”之后的一些新元素中,如下所示:

<Totals>
 <Totalproduct>
    <Basisproduct>110</Basisproduct>
    <Cumul_Amount>1,52</CustInvoice_LineAmount>
  </Totalproduct>
 <Totalproduct>
    <Basisproduct>198</Basisproduct>
    <Cumul_Amount>294,77</CustInvoice_LineAmount>
  </Totalproduct>
 <Totalproduct>
    <Basisproduct>992</Basisproduct>
    <Cumul_Amount>163,32</CustInvoice_LineAmount>
  </Totalproduct>
 <Totalproduct>
    <Basisproduct>993</Basisproduct>
    <Cumul_Amount>193,78</CustInvoice_LineAmount>
  </Totalproduct>
<Totals>

<-----I have this xml as an input.------>

<?xml version="1.0" encoding="utf-8"?>
<Report Name="SalesInvoice">
    <ReportName>SalesInvoice</ReportName>
  <Invoice>
    <InvoicingName>Test Company</InvoicingName>
  </Invoice>
  <ConditionalArea>
      <BodyCustInvoice>
        <Basisproduct>110</Basisproduct>
        <CustInvoice_LineAmount>1,52</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
        <Basisproduct>198</Basisproduct>
        <CustInvoice_LineAmount>20,11</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
        <Basisproduct>198</Basisproduct>
        <CustInvoice_LineAmount>20,22</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
        <Basisproduct>992</Basisproduct>
        <CustInvoice_LineAmount>3033</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
        <Basisproduct>993</Basisproduct>
        <CustInvoice_LineAmount>30,34</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
        <Basisproduct>992</Basisproduct>
        <CustInvoice_LineAmount>30,35</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
        <Basisproduct>992</Basisproduct>
        <CustInvoice_LineAmount>30.45</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
        <Basisproduct>993</Basisproduct>
        <CustInvoice_LineAmount>30,46</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
        <Basisproduct>198</Basisproduct>
        <CustInvoice_LineAmount>100.99</CustInvoice_LineAmount>
      </BodyCustInvoice>,      </ConditionalArea>
  <Totals>
  </Totals>
</Report>

我用来计算“Basisproduct”的累积和的xsl是:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">              <xsl:output indent="yes"/>       <xsl:strip-space elements="*"/>

<xsl:decimal-format name="EU" decimal-separator="," grouping-separator="."/>

<xsl:key name="KType" match="Basisproduct" use="."/>
    <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
   </xsl:template>

    <xsl:template match="TotalSBasis">
     <TotalSBasis>
       <xsl:for-each select="/*/*/*/Basisproduct [generate-id() = generate-id(key  ('KType', .)[1])]">
         <xsl:variable name="currProd" select="."/>
         <Totalproduct>
           <xsl:copy-of select="."/>
           <Cumul_Amount>
             <xsl:value-of select="sum(/*/*/BodyCustInvoiceTrans  [Basisproduct=$currProd]/CustInvoiceTrans_LineAmount)"/>
           </Cumul_Amount>
         </Totalproduct>
       </xsl:for-each>
           </TotalSBasis>
   </xsl:template>
  </xsl:stylesheet>

4 个答案:

答案 0 :(得分:0)

<Totals>
  <xsl:for-each select="*/*/*/Basisproduct [generate-id() = generate-id(key  ('KType', .)[1])]">
    <Totalproduct>
      <Basisproduct><xsl:value-of select= "."/></Basisproduct>
      <Cumul_Amount>
        <xsl:value-of select= "/*/*/*[Basisproduct = current()][last()]/CustInvoice_LineAmount + sum(/*/*/*[Basisproduct = current()][last()]/preceding-sibling::*/CustInvoice_LineAmount)"/>
      </Cumul_Amount>
    </Totalproduct>
  </xsl:for-each>
</Totals>

这将以所提及的结果输出xml,并显示您显示的结果。

答案 1 :(得分:0)

编辑:更新了我的XSLT,以适应OP的请求,将总数插入原始XML。解决问题的诀窍是使用身份模板和全局变量。

如果您使用此XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="KType" match="Basisproduct" use="."/>
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <!-- create a variable w/ the calculated totals -->
    <xsl:variable name="CalculatedTotals">
        <xsl:for-each select="*/*/*/Basisproduct [generate-id() = generate-id(key  ('KType', .)[1])]">
            <xsl:element name="TotalProduct">
                <xsl:element name="Basisproduct">
                    <xsl:value-of select= "."/>
                </xsl:element>
                <xsl:element name="Cumul_Amount">
                    <xsl:value-of select= "/*/*/*[Basisproduct = current()][last()]/CustInvoice_LineAmount + sum(/*/*/*[Basisproduct = current()][last()]/preceding-sibling::*/CustInvoice_LineAmount)"/>
                </xsl:element>
            </xsl:element>
        </xsl:for-each>
    </xsl:variable>

    <!-- identity -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <!-- root -->
    <xsl:template match="/">
        <xsl:apply-templates select="node()|@*"/>
    </xsl:template>    

    <xsl:template match="Totals">
        <xsl:copy>
            <!-- insert the calculated totals -->
            <xsl:copy-of select="$CalculatedTotals"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

您将获得此XML输出:

<?xml version="1.0" encoding="utf-8"?>
<Report Name="SalesInvoice">
   <ReportName>SalesInvoice</ReportName>
   <Invoice>
      <InvoicingName>Test Company</InvoicingName>
   </Invoice>
   <ConditionalArea>
      <BodyCustInvoice>
         <Basisproduct>110</Basisproduct>
         <CustInvoice_LineAmount>1.52</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>198</Basisproduct>
         <CustInvoice_LineAmount>20.11</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>198</Basisproduct>
         <CustInvoice_LineAmount>20.22</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>992</Basisproduct>
         <CustInvoice_LineAmount>30.33</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>993</Basisproduct>
         <CustInvoice_LineAmount>30.34</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>992</Basisproduct>
         <CustInvoice_LineAmount>30.35</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>992</Basisproduct>
         <CustInvoice_LineAmount>30.45</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>993</Basisproduct>
         <CustInvoice_LineAmount>30.46</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>198</Basisproduct>
         <CustInvoice_LineAmount>100.99</CustInvoice_LineAmount>
      </BodyCustInvoice>
   </ConditionalArea>
   <Totals>
      <TotalProduct>
         <Basisproduct>110</Basisproduct>
         <Cumul_Amount>1.52</Cumul_Amount>
      </TotalProduct>
      <TotalProduct>
         <Basisproduct>198</Basisproduct>
         <Cumul_Amount>294.77</Cumul_Amount>
      </TotalProduct>
      <TotalProduct>
         <Basisproduct>992</Basisproduct>
         <Cumul_Amount>163.32</Cumul_Amount>
      </TotalProduct>
      <TotalProduct>
         <Basisproduct>993</Basisproduct>
         <Cumul_Amount>193.78000000000003</Cumul_Amount>
      </TotalProduct>
   </Totals>
</Report>

在Win 7上使用Oxygen 12测试。

答案 2 :(得分:0)

您应该做的是使用身份转换,然后覆盖Totals元素。

编辑:根据OP在@james.garriss回答中的评论,我将计算修改为仅对所有内容求和。

输入XML

<Report Name="SalesInvoice">
  <ReportName>SalesInvoice</ReportName>
  <Invoice>
    <InvoicingName>Test Company</InvoicingName>
  </Invoice>
  <ConditionalArea>
    <BodyCustInvoice>
      <Basisproduct>110</Basisproduct>
      <CustInvoice_LineAmount>1.52</CustInvoice_LineAmount>
    </BodyCustInvoice>
    <BodyCustInvoice>
      <Basisproduct>198</Basisproduct>
      <CustInvoice_LineAmount>20.11</CustInvoice_LineAmount>
    </BodyCustInvoice>
    <BodyCustInvoice>
      <Basisproduct>198</Basisproduct>
      <CustInvoice_LineAmount>20.22</CustInvoice_LineAmount>
    </BodyCustInvoice>
    <BodyCustInvoice>
      <Basisproduct>992</Basisproduct>
      <CustInvoice_LineAmount>30.33</CustInvoice_LineAmount>
    </BodyCustInvoice>
    <BodyCustInvoice>
      <Basisproduct>993</Basisproduct>
      <CustInvoice_LineAmount>30.34</CustInvoice_LineAmount>
    </BodyCustInvoice>
    <BodyCustInvoice>
      <Basisproduct>992</Basisproduct>
      <CustInvoice_LineAmount>30.35</CustInvoice_LineAmount>
    </BodyCustInvoice>
    <BodyCustInvoice>
      <Basisproduct>992</Basisproduct>
      <CustInvoice_LineAmount>30.45</CustInvoice_LineAmount>
    </BodyCustInvoice>
    <BodyCustInvoice>
      <Basisproduct>993</Basisproduct>
      <CustInvoice_LineAmount>30.46</CustInvoice_LineAmount>
    </BodyCustInvoice>
    <BodyCustInvoice>
      <Basisproduct>198</Basisproduct>
      <CustInvoice_LineAmount>100.99</CustInvoice_LineAmount>
    </BodyCustInvoice>
  </ConditionalArea>
  <Totals> </Totals>
</Report>

XSLT样式表

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="KType" match="Basisproduct" use="."/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Totals">
    <Totals>
      <xsl:for-each select="/*/*/*/Basisproduct [generate-id() = generate-id(key  ('KType', .)[1])]">
        <xsl:variable name="currProd" select="."/>
        <Totalproduct>
          <xsl:copy-of select="."/>
          <Cumul_Amount>
            <!--<xsl:value-of select= "/*/*/*[Basisproduct = current()][last()]/CustInvoice_LineAmount + sum(/*/*/*[Basisproduct = current()][last()]/preceding-sibling::*/CustInvoice_LineAmount)"/>-->
            <xsl:value-of select="sum(/*/*/BodyCustInvoice[Basisproduct=$currProd]/CustInvoice_LineAmount)"/>
          </Cumul_Amount>
        </Totalproduct>
      </xsl:for-each>      
    </Totals>
  </xsl:template>

</xsl:stylesheet>

输出XML (使用Xalan :-()

<Report Name="SalesInvoice">
   <ReportName>SalesInvoice</ReportName>
   <Invoice>
      <InvoicingName>Test Company</InvoicingName>
   </Invoice>
   <ConditionalArea>
      <BodyCustInvoice>
         <Basisproduct>110</Basisproduct>
         <CustInvoice_LineAmount>1.52</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>198</Basisproduct>
         <CustInvoice_LineAmount>20.11</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>198</Basisproduct>
         <CustInvoice_LineAmount>20.22</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>992</Basisproduct>
         <CustInvoice_LineAmount>30.33</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>993</Basisproduct>
         <CustInvoice_LineAmount>30.34</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>992</Basisproduct>
         <CustInvoice_LineAmount>30.35</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>992</Basisproduct>
         <CustInvoice_LineAmount>30.45</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>993</Basisproduct>
         <CustInvoice_LineAmount>30.46</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>198</Basisproduct>
         <CustInvoice_LineAmount>100.99</CustInvoice_LineAmount>
      </BodyCustInvoice>
   </ConditionalArea>
   <Totals>
      <Totalproduct>
         <Basisproduct>110</Basisproduct>
         <Cumul_Amount>1.52</Cumul_Amount>
      </Totalproduct>
      <Totalproduct>
         <Basisproduct>198</Basisproduct>
         <Cumul_Amount>141.32</Cumul_Amount>
      </Totalproduct>
      <Totalproduct>
         <Basisproduct>992</Basisproduct>
         <Cumul_Amount>91.13</Cumul_Amount>
      </Totalproduct>
      <Totalproduct>
         <Basisproduct>993</Basisproduct>
         <Cumul_Amount>60.8</Cumul_Amount>
      </Totalproduct>
   </Totals>
</Report>

答案 3 :(得分:0)

此变换按Basisproduct对元素进行分组,并计算每个组的总和。请注意,它包含identity.xsl众所周知的Identity Transformation


[XSLT 1.0]

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:include href="identity.xsl"/>

    <xsl:key name="KType" match="BodyCustInvoice" use="Basisproduct"/>

    <xsl:template match="Totals">
        <Totals>
            <xsl:apply-templates select="
                preceding-sibling::ConditionalArea[1]/BodyCustInvoice
                [generate-id() 
                = generate-id(key  ('KType', Basisproduct)[1])]" mode="totals"/>
        </Totals>
    </xsl:template>

    <xsl:template match="BodyCustInvoice" mode="totals">
        <Totalproduct>
            <Basisproduct><xsl:value-of select="Basisproduct"/></Basisproduct>
            <Cumul_Amount>  
                <xsl:value-of select="
                    sum(key('KType',Basisproduct)/CustInvoice_LineAmount)"/>
            </Cumul_Amount>
        </Totalproduct>
    </xsl:template>

</xsl:stylesheet>

输出:

<Report Name="SalesInvoice">
   <ReportName>SalesInvoice</ReportName>
   <Invoice>
      <InvoicingName>Test Company</InvoicingName>
   </Invoice>
   <ConditionalArea>
      <BodyCustInvoice>
         <Basisproduct>110</Basisproduct>
         <CustInvoice_LineAmount>1.52</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>198</Basisproduct>
         <CustInvoice_LineAmount>20.11</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>198</Basisproduct>
         <CustInvoice_LineAmount>20.22</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>992</Basisproduct>
         <CustInvoice_LineAmount>30.33</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>993</Basisproduct>
         <CustInvoice_LineAmount>30.34</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>992</Basisproduct>
         <CustInvoice_LineAmount>30.35</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>992</Basisproduct>
         <CustInvoice_LineAmount>30.45</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>993</Basisproduct>
         <CustInvoice_LineAmount>30.46</CustInvoice_LineAmount>
      </BodyCustInvoice>
      <BodyCustInvoice>
         <Basisproduct>198</Basisproduct>
         <CustInvoice_LineAmount>100.99</CustInvoice_LineAmount>
      </BodyCustInvoice>
   </ConditionalArea>
   <Totals>
      <Totalproduct>
         <Basisproduct>110</Basisproduct>
         <Cumul_Amount>1.52</Cumul_Amount>
      </Totalproduct>
      <Totalproduct>
         <Basisproduct>198</Basisproduct>
         <Cumul_Amount>141.32</Cumul_Amount>
      </Totalproduct>
      <Totalproduct>
         <Basisproduct>992</Basisproduct>
         <Cumul_Amount>91.13</Cumul_Amount>
      </Totalproduct>
      <Totalproduct>
         <Basisproduct>993</Basisproduct>
         <Cumul_Amount>60.8</Cumul_Amount>
      </Totalproduct>
   </Totals>
</Report>