2012-12-13 90 views
0

我是XSLT的初學者,並使用它通過Java將XML轉換爲XML。帶分組的XSLT 1.0計算

源XML:

<Response> 
    <Data> 
     <Book name="A" value="1"/> 
     <Book name="B" value="2"/> 
     <Book name="C" value="1"/> 
    </Data> 
    <Result> 
     <Prices> 
      <Price type="A" value="100"/> 
      <Price type="B" value="60"/> 
      <Price type="C" value="40"/> 
     </Prices> 
    </Result> 
</Response> 

XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" indent="yes" /> 

    <xsl:template match="/"> 
     <xsl:element name="Books"> 
      <xsl:variable name="BookType" select="//@type" /> 
      <xsl:attribute name="Total"> 
       <xsl:value-of select="sum(//Price[@type=$BookType]/@value)"/> 
      </xsl:attribute> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

輸出XML:

<Books Total="200"/> 

預期輸出XML:

<Books Total="260"/> 

在源XML我收到沒有一本書和它的價格,但他們是不相關的。

<Price>標記表示一本書的價格。 我需要計算的所有書籍的總價格如下

Price of one book x no of books 
For A : 100 x 1 = 100 
For B : 60 x 2 = 120 
For C : 40 x 1 = 040 
------------------------ 
Total Price is = 260 

請幫助。

回答

1

的最簡單的方法是建立在包含「價格*數量」的值的變量的暫時結構,然後使用exslt:node-set擴展函數來彙總這些值

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
       xmlns:exslt="http://exslt.org/common" 
       exclude-result-prefixes="exslt"> 
    <xsl:output method="xml" indent="yes" /> 

    <xsl:template match="/"> 
    <xsl:variable name="subTotals"> 
     <xsl:for-each select="/Response/Data/Book"> 
     <totalPrice> 
      <xsl:value-of select="@value * 
      /Response/Result/Prices/Price[@type = current()/@name]/@value" /> 
     </totalPrice> 
     </xsl:for-each> 
    </xsl:variable> 
    <Books Total="{sum(exslt:node-set($subTotals)/totalPrice)}" /> 
    </xsl:template> 
</xsl:stylesheet> 

能夠在不使用擴展函數的情況下,在純XSLT 1.0中執行此操作,但它非常煩瑣,需要將累加器參數傳遞到模板鏈中:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" indent="yes" /> 

    <xsl:template match="/"> 
    <Books> 
     <xsl:apply-templates select="/Response/Data/Book[1]" /> 
    </Books> 
    </xsl:template> 

    <xsl:template match="Book"> 
    <xsl:param name="runningTotal" select="0" /> 
    <xsl:variable name="thisBookTotal" select="@value * 
     /Response/Result/Prices/Price[@type = current()/@name]/@value" /> 
    <xsl:choose> 
     <xsl:when test="following-sibling::Book"> 
     <!-- There are more books, process the next one, passing an updated 
      running total --> 
     <xsl:apply-templates select="following-sibling::Book[1]"> 
      <xsl:with-param name="runningTotal" select="$runningTotal + $thisBookTotal" /> 
     </xsl:apply-templates> 
     </xsl:when> 
     <xsl:otherwise> 
     <!-- There are no more books, produce the final total --> 
     <xsl:attribute name="Total"> 
      <xsl:value-of select="$runningTotal + $thisBookTotal" /> 
     </xsl:attribute> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet>