2013-09-24 2 views
0

계좌 번호와 금액과 관련된 통화를 기반으로 거래를 추가하려고합니다.XSLT : 2 개의 자식 요소를 기반으로하는 요소의 수학적 추가

다음은 원래 xml입니다. 최대 1000 개의 트랜잭션이있을 것으로 예상됩니다. 이 예에서는 AUD 및 HKD의 두 계정에서 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> 

내가 가지고 얼마나 멀리이다. 전용 계정

당신은 XSLT를 사용에 필수적 "프로그래밍 같은"접근 방식에 너무 깊이 갔어요
<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 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

Genius! 나는 내 자신이 어떻게 돌아서 뒤집어 질지 모르겠다. 너는 학생이라고 했으므로 나는 네가 강사라고 생각하고있다. XSLT를 더 잘 이해하기 위해 사용할 수있는 무료 콘텐츠를 어딘가에서 온라인으로 제공하지 않겠습니까? –

+0

저는 1999 년 XSLT가 마무리되기 전부터 전 세계에서 XSLT를 가르 칠 수있는 특권을 누 렸습니다. OASIS XSLT 및 XPath 적합성 기술위원회의 창립 회장이었습니다. 예, 무료 스트리밍을 위해 5 시간 분량의 내 동영상 강의를 사용할 수 있습니다. StackOverflow 프로필을 질문 포럼에 게시하기에 적합하지 않은 정보로 업데이트했습니다. XML 작업에 대한 행운을 비세요! –