总结每个客户的发票总额

时间:2012-09-09 12:10:45

标签: xslt xslt-1.0

我需要一种方法来计算每个客户的发票总数,(添加三张发票然后相应地显示总额),已经尝试了总和(/ * /(PriceUnit * Ordered)),但是没有工作的错误,.--- [总发票= PriceUnit * Ordered],所以总结三张发票然后显示结果,对我来说很难,所以请帮忙

示例输入文档

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Nom.xslt"?>
<customers>
  <customer>
    <clientname>troy madison</clientname>
    <invoices>
    <invoiceDate>8/8/98</invoiceDate>
      <product>
         <PriceUnit>1000</PriceUnit>
         <Ordered>2</Ordered>
     </product>
     <product>
         <PriceUnit>5400</PriceUnit>
         <Ordered>3</Ordered>
     </product>
   </invoices>
   <invoices>
     <invoiceDate>1/4/98</invoiceDate>
       <product>
          <PriceUnit>300</PriceUnit>
          <Ordered>4</Ordered>
       </product>
      <product>
        <PriceUnit>6000</PriceUnit>
        <Ordered>1</Ordered>
     </product>
   </invoices>
  <invoices>
    <invoiceDate>03/5/99</invoiceDate>
      <product>
        <PriceUnit>549</PriceUnit>
        <Ordered>1</Ordered>
     </product>
     <product>
       <PriceUnit>320</PriceUnit>
       <Ordered>2</Ordered>
    </product>
   </invoices>
 </customer>
 <customer>
   <clientname>Morris</clientname>
    <invoices>
      <invoiceDate>1/1/00</invoiceDate>
        <product>
           <PriceUnit>59</PriceUnit>
           <Ordered>3</Ordered>
        </product>
      <product>
          <PriceUnit>55</PriceUnit>
          <Ordered>1</Ordered>
      </product>
    </invoices>
    <invoices>
     <invoiceDate>11/1/01</invoiceDate>
       <product>
         <PriceUnit>10</PriceUnit>
         <Ordered>2</Ordered>
      </product>
      <product>
         <PriceUnit>54</PriceUnit>
         <Ordered>1</Ordered>
       </product>
    </invoices>
    <invoices>
      <invoiceDate>03/2/01</invoiceDate>
        <product>
          <PriceUnit>30</PriceUnit>
          <Ordered>1</Ordered>
        </product>
       <product>
         <PriceUnit>299</PriceUnit>
         <Ordered>1</Ordered>
       </product>
    </invoices>
</customer>
</customers>

预期输出

[OP在此处列出预期输出。]

到目前为止我尝试过的样式表

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="customers">
    <html>
        <head>
            <h1>CUSTOMER REFERENCE</h1>
        </head>
        <body bgcolor="#DAF52C">
            <table border="1">
                <tr>
                    <th width="50">NAME</th>
                    <th width="50">INVOICE DATE</th>
                    <th width="50">PRODUCT UNIT</th>
                    <th width="50">ORDERED </th>
                    <th width="50">PRODUCT UNIT</th>
                    <th width="50">ORDERED </th>
                    <th width="50">INVOICE DATE</th>
                    <th width="50">PRODUCT UNIT</th>
                    <th width="50">ORDERED </th>
                    <th width="50">PRODUCT UNIT</th>
                    <th width="50">ORDERED </th>
                    <th width="50">INVOICE DATE</th>
                    <th width="50">PRODUCT UNIT</th>
                    <th width="50">ORDERED </th>
                    <th width="50">PRODUCT UNIT</th>
                    <th width="50">ORDERED </th>
                    <th width="50">INVOICE TOTAL</th>
                </tr>
                <xsl:for-each select="customer">
                    <tr>
                        <td><xsl:value-of select="clientname"/></td>
                        <xsl:for-each select="invoices">
                            <td><xsl:value-of select="invoiceDate"/></td>
                            <xsl:for-each select="product">
                                <td><xsl:value-of select="PriceUnit"/></td>
                                <td><xsl:value-of select="Ordered"/></td>
                            </xsl:for-each>
                        </xsl:for-each>
                    </tr>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>
</xsl:stylesheet>

2 个答案:

答案 0 :(得分:0)

这是您第一次发布此问题的XSLT 1.0等效Dimitre's answer

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  xmlns:so="https://stackoverflow.com/questions/12338944"
  exclude-result-prefixes="xsl exsl so">
<xsl:output method="html" />
<xsl:strip-space elements="*" />

 <xsl:template match="/*">
  <html>
    <table border="1">
     <thead>
       <tr>
         <td>Name</td><td>Total</td>
       </tr>
     </thead>
     <xsl:apply-templates/>
    </table>
  </html>
 </xsl:template>

 <xsl:template match="customer">
  <tr>
    <td><xsl:value-of select="clientname"/></td>
    <td>
      <xsl:variable name="sales">
        <xsl:for-each select="invoices/product">
          <so:sale><xsl:value-of select="PriceUnit * Ordered"/></so:sale>
        </xsl:for-each>
      </xsl:variable>
      <xsl:value-of select="sum(exsl:node-set($sales)/so:sale)"/>
      </td>
  </tr>
 </xsl:template>
</xsl:stylesheet>

在示例文档中,这会产生输出...

<html>
  <table border="1">
    <thead>
      <tr>
        <td>Name</td>
        <td>Total</td>
      </tr>
    </thead>
    <tr>
      <td>troy madison</td>
      <td>26589</td>
    </tr>
    <tr>
      <td>Morris</td>
      <td>635</td>
    </tr>
  </table>
</html>

答案 1 :(得分:0)

这是一个纯XSLT 1.0解决方案,不需要任何扩展功能:

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

 <xsl:template match="/*">
  <html>
    <table border="1">
     <thead>
       <tr>
         <td>Name</td><td>Total</td>
       </tr>
     </thead>
     <xsl:apply-templates/>
    </table>
  </html>
 </xsl:template>

 <xsl:template match="customer">
  <tr>
    <td><xsl:value-of select="clientname"/></td>
    <td>
      <xsl:call-template name="sumProducts">
       <xsl:with-param name="pNodes" select="invoices/product"/>
       <xsl:with-param name="pName1" select="'PriceUnit'"/>
       <xsl:with-param name="pName2" select="'Ordered'"/>
      </xsl:call-template>
    </td>
  </tr>
 </xsl:template>

 <xsl:template name="sumProducts">
   <xsl:param name="pNodes"/>
   <xsl:param name="pName1"/>
   <xsl:param name="pName2"/>
   <xsl:param name="pAccum" select="0"/>

   <xsl:choose>
     <xsl:when test="not($pNodes)">
       <xsl:value-of select="$pAccum"/>
     </xsl:when>
     <xsl:otherwise>
      <xsl:call-template name="sumProducts">
        <xsl:with-param name="pNodes" select="$pNodes[position() >1]"/>
        <xsl:with-param name="pName1" select="$pName1"/>
        <xsl:with-param name="pName2" select="$pName2"/>
        <xsl:with-param name="pAccum" select=
        "$pAccum + $pNodes[1]/*[name()=$pName1] * $pNodes[1]/*[name()=$pName2]"/>
      </xsl:call-template>
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时:

<customers>
    <customer>
        <clientname>troy madison</clientname>
        <invoices>
            <invoiceDate>8/8/98</invoiceDate>
            <product>
                <PriceUnit>1000</PriceUnit>
                <Ordered>2</Ordered>
            </product>
            <product>
                <PriceUnit>5400</PriceUnit>
                <Ordered>3</Ordered>
            </product>
        </invoices>
        <invoices>
            <invoiceDate>1/4/98</invoiceDate>
            <product>
                <PriceUnit>300</PriceUnit>
                <Ordered>4</Ordered>
            </product>
            <product>
                <PriceUnit>6000</PriceUnit>
                <Ordered>1</Ordered>
            </product>
        </invoices>
        <invoices>
            <invoiceDate>03/5/99</invoiceDate>
            <product>
                <PriceUnit>549</PriceUnit>
                <Ordered>1</Ordered>
            </product>
            <product>
                <PriceUnit>320</PriceUnit>
                <Ordered>2</Ordered>
            </product>
        </invoices>
    </customer>
    <customer>
        <clientname>Morris</clientname>
        <invoices>
            <invoiceDate>1/1/00</invoiceDate>
            <product>
                <PriceUnit>59</PriceUnit>
                <Ordered>3</Ordered>
            </product>
            <product>
                <PriceUnit>55</PriceUnit>
                <Ordered>1</Ordered>
            </product>
        </invoices>
        <invoices>
            <invoiceDate>11/1/01</invoiceDate>
            <product>
                <PriceUnit>10</PriceUnit>
                <Ordered>2</Ordered>
            </product>
            <product>
                <PriceUnit>54</PriceUnit>
                <Ordered>1</Ordered>
            </product>
        </invoices>
        <invoices>
            <invoiceDate>03/2/01</invoiceDate>
            <product>
                <PriceUnit>30</PriceUnit>
                <Ordered>1</Ordered>
            </product>
            <product>
                <PriceUnit>299</PriceUnit>
                <Ordered>1</Ordered>
            </product>
        </invoices>
    </customer>
</customers>

产生了想要的正确结果

<html>
   <table border="1">
      <thead>
         <tr>
            <td>Name</td>
            <td>Total</td>
         </tr>
      </thead>
      <tr>
         <td>troy madison</td>
         <td>26589</td>
      </tr>
      <tr>
         <td>Morris</td>
         <td>635</td>
      </tr>
   </table>
</html>

<强>解释

  1. 递归调用命名模板(sumProducts),它将子项的产品应该求和的节点的节点集($pNodes)作为参数。在两个子元素($pName1$pName2)中,应将其值的乘积相加。最后一个辅助参数$pAccum的初始值为0,用于存储每次递归调用之间的累积结果。

  2. 停止条件是传递的pNodes节点集为空时。在这种情况下,我们输出累计和($pAccum)。

  3. 如果停止条件为false,我们会使用$pNodes调用自己,其中第一个节点已移除,并且新值为$pAccum,我们已将其添加到当前产品中

  4. 请注意

    sumProducts模板非常通用,可用于需要产品总和的任何情况。

    因此,无论何时需要产品总数,它都应该放在自己的样式表文件中,其他样式表将导入