2013-09-24 127 views
0

我試圖根據帳號和與金額關聯的貨幣添加交易。XSLT:基於2個子元素的數學元素添加

這裏是原始的xml: 我預計至多有1000個事務。在這個例子中,我有兩個賬戶以澳元和港幣交易5筆交易。我希望將所有金額,每種貨幣,每筆交易添加爲1行。

<transactionlist> 
    <transaction> 
     <accountnumber>1</accountnumber> 
     <amount>100</amount> 
     <currency>AUD</currency> 
    </transaction> 
    <transaction> 
     <accountnumber>1</accountnumber> 
     <amount>50</amount> 
     <currency>AUD</currency> 
    </transaction> 
    <transaction> 
     <accountnumber>1</accountnumber> 
     <amount>100</amount> 
     <currency>HKD</currency> 
    </transaction> 
    <transaction> 
     <accountnumber>1</accountnumber> 
     <amount>500</amount> 
     <currency>HKD</currency> 
    </transaction> 
    <transaction> 
     <accountnumber>2</accountnumber> 
     <amount>200</amount> 
     <currency>AUD</currency> 
    </transaction> 
</transactionlist> 

這是預期的輸出(計數是怎麼添加了很多交易,以創建一個新的行):

<transactionlist> 
    <row> 
     <accountnumber>1</accountnumber> 
     <totalamount>150</totalamount> 
     <currency>AUD</currency> 
     <count>2</count> 
    </row> 
    <row> 
     <accountnumber>1</accountnumber> 
     <totalamount>600</totalamount> 
     <currency>HKD</currency> 
     <count>2</count> 
    </row> 
    <row> 
     <accountnumber>2</accountnumber> 
     <totalamount>200</totalamount> 
     <currency>AUD</currency> 
     <count>1</count> 
    </row> 
</transactionlist> 

這裏是我多遠了。只是不知道如何去只能由貨幣的帳戶

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

    <xsl:template match="/"> 
    <transactionlist> 
     <xsl:apply-templates select="transactionlist/transaction" /> 
    </transactionlist> 
    </xsl:template> 

    <xsl:template match="transaction"> 
    <!-- only do work for the *first* transaction with any particular ID --> 
    <xsl:if test="not(preceding-sibling::transaction/accountnumber = current()/accountnumber)"> 
     <row> 
     <xsl:copy-of select="accountnumber" /> 
     <totalamount> 
      <xsl:call-template name="running-total-byaccount"> 
      <xsl:with-param name="values" select="/transactionlist/transaction[accountnumber = current()/accountnumber]" /> 
      </xsl:call-template> 
     </totalamount> 
     </row> 
    </xsl:if> 
    </xsl:template> 

    <xsl:template name="running-total-byaccount"> 
    <xsl:param name="values" /> 
    <xsl:choose> 
     <xsl:when test="count($values)"> 
     <xsl:variable name="curr" select="$values[1]" /> 
     <xsl:variable name="rest" select="$values[position() &gt; 1]" /> 
     <!-- recursive step: calculate the total of all remaining values --> 
     <xsl:variable name="subtotal"> 
      <xsl:call-template name="running-total-byaccount"> 
      <xsl:with-param name="values" select="$rest" /> 
      </xsl:call-template> 
     </xsl:variable> 
     <xsl:value-of select="$subtotal + $curr/amount" /> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="0" /> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 


</xsl:stylesheet> 

回答

4

你已經走了有必要「編程式」的方式來使用XSLT太深分組每筆交易增加。我建議我的學生使用分組方法進行聲明式自上而下的方法是處理像您這樣的需求的最佳方法。

在XSLT 1.0的分組方法中,由於組的嵌套特性,您的問題向我提出了基於變量的分組方法。 XSLT 2.0使這更容易,但是你已經在樣式表中聲明瞭XSLT 1.0,所以我認爲這是對你的限制。

我扔在一起的一個快速解決方案是在下面的成績單。我希望這有幫助。您可以看到它避免了遞歸的所有問題,並將需求分解爲分組問題。

數據:

T:\ftemp>type currency.xml 
<transactionlist> 
    <transaction> 
     <accountnumber>1</accountnumber> 
     <amount>100</amount> 
     <currency>AUD</currency> 
    </transaction> 
    <transaction> 
     <accountnumber>1</accountnumber> 
     <amount>50</amount> 
     <currency>AUD</currency> 
    </transaction> 
    <transaction> 
     <accountnumber>1</accountnumber> 
     <amount>100</amount> 
     <currency>HKD</currency> 
    </transaction> 
    <transaction> 
     <accountnumber>1</accountnumber> 
     <amount>500</amount> 
     <currency>HKD</currency> 
    </transaction> 
    <transaction> 
     <accountnumber>2</accountnumber> 
     <amount>200</amount> 
     <currency>AUD</currency> 
    </transaction> 
</transactionlist> 

執行和結果:

T:\ftemp>call xslt currency.xml currency.xsl 
<?xml version="1.0" encoding="utf-8"?> 
<transactionlist> 
    <row> 
     <accountnumber>1</accountnumber> 
     <totalamount>150</totalamount> 
     <currency>AUD</currency> 
     <count>2</count> 
    </row> 
    <row> 
     <accountnumber>1</accountnumber> 
     <totalamount>600</totalamount> 
     <currency>HKD</currency> 
     <count>2</count> 
    </row> 
    <row> 
     <accountnumber>2</accountnumber> 
     <totalamount>200</totalamount> 
     <currency>AUD</currency> 
     <count>1</count> 
    </row> 
</transactionlist> 

樣式表:

T:\ftemp>type currency.xsl 
<?xml version="1.0" encoding="US-ASCII"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       version="1.0"> 

<xsl:output indent="yes"/> 

<xsl:template match="transactionlist"> 
    <transactionlist> 
    <xsl:variable name="trans" select="transaction"/> 
    <xsl:for-each select="$trans"> 
     <!--find all unique accounts--> 
     <xsl:if test="generate-id(.)= 
      generate-id($trans[accountnumber=current()/accountnumber][1])"> 
     <xsl:variable name="acc" 
        select="$trans[accountnumber=current()/accountnumber]"/> 
     <xsl:for-each select="$acc"> 
      <!--find all unique currencies in the accounts--> 
      <xsl:if test="generate-id(.)= 
         generate-id($acc[currency=current()/currency][1])"> 
      <!--note all for the given currency--> 
      <xsl:variable name="curr" 
          select="$acc[currency=current()/currency]"/> 
      <row> 
       <xsl:copy-of select="accountnumber"/> 
       <totalamount> 
       <xsl:value-of select="sum($curr/amount)"/> 
       </totalamount> 
       <xsl:copy-of select="currency"/> 
       <count> 
       <xsl:value-of select="count($curr)"/> 
       </count> 
      </row>    
      </xsl:if> 
     </xsl:for-each> 
     </xsl:if> 
    </xsl:for-each> 
    </transactionlist> 
</xsl:template> 

</xsl:stylesheet> 

編輯:修復錯別字和可讀性收集貨幣值。

+0

天才!我不知道我是如何讓自己全部轉身顛倒的。你說學生,所以我假設你是講師。您不會碰巧在某處有免費內容,我可以用它來更好地理解XSLT嗎? –

+0

自從1999年XSLT完成之前,我就有幸在世界各地教XSLT,並且我是OASIS XSLT和XPath一致性技術委員會的創始主席。是的,我的視頻指令有五個小時可用於免費流媒體。我更新了我的StackOverflow配置文件,信息不適合發佈在問題論壇中。祝您在XML中工作順利! –