2013-05-13 114 views
2

我正在嘗試將具有相同值的兄弟姐妹緊接在一起。但是我很難僅選擇IMMEDIATE兄弟姐妹。使用XPath - 如何選擇/計算即時兄弟?

輸入:

<ROWS> 
    <ROW> 
     <MONTH>1</MONTH> 
     <START_DATE>15/04/2013</START_DATE> 
     <RATE_AMOUNT>10</RATE_AMOUNT> 
     <DISCOUNT>-2</DISCOUNT> 
    </ROW> 
    <ROW> 
     <MONTH>2</MONTH> 
     <START_DATE>15/05/2013</START_DATE> 
     <RATE_AMOUNT>10</RATE_AMOUNT> 
     <DISCOUNT>-2</DISCOUNT> 
    </ROW> 
    <ROW> 
     <MONTH>3</MONTH> 
     <START_DATE>15/06/2013</START_DATE> 
     <RATE_AMOUNT>10</RATE_AMOUNT> 
     <DISCOUNT>-5</DISCOUNT> 
    </ROW> 
    <ROW> 
     <MONTH>4</MONTH> 
     <START_DATE>15/07/2013</START_DATE> 
     <RATE_AMOUNT>10</RATE_AMOUNT> 
     <DISCOUNT>-2</DISCOUNT> 
    </ROW> 
</ROWS> 

預期輸出:

<RateList> 
    <Rate> 
     <NoOfMonths>2</NoOfMonths> 
     <StartDate>15/04/2013</StartDate> 
     <RateAmount>10</RateAmount> 
     <Discount>-2</Discount> 
    </Rate> 
    <Rate> 
     <NoOfMonths>1</NoOfMonths> 
     <StartDate>15/06/2013</StartDate> 
     <RateAmount>10</RateAmount> 
     <Discount>-5</Discount> 
    </Rate> 
    <Rate> 
     <NoOfMonths>1</NoOfMonths> 
     <StartDate>15/07/2013</StartDate> 
     <RateAmount>10</RateAmount> 
     <Discount>-2</Discount> 
    </Rate> 
</RateList> 

這是我的XSL:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/"> 
     <RateList> 
      <xsl:apply-templates/> 
     </RateList> 
    </xsl:template> 
    <xsl:template match="ROW"> 
     <xsl:variable name="noOfMonths" select=".|following-sibling::*[RATE_AMOUNT=current()/RATE_AMOUNT][DISCOUNT=current()/DISCOUNT]"/> 
     <xsl:if test="not(preceding-sibling::*[RATE_AMOUNT=current()/RATE_AMOUNT][DISCOUNT=current()/DISCOUNT])"> 
      <Rate> 
       <NoOfMonths> 
        <xsl:value-of select="count($noOfMonths)"/> 
       </NoOfMonths>  
       <StartDate> 
        <xsl:value-of select="START_DATE"/> 
       </StartDate> 
       <RateAmount> 
        <xsl:value-of select="RATE_AMOUNT"/> 
       </RateAmount> 
       <Discount> 
        <xsl:value-of select="DISCOUNT"/> 
       </Discount> 
      </Rate> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

這是我得到的輸出:

<RateList> 
    <Rate> 
     <NoOfMonths>3</NoOfMonths> 
     <StartDate>15/04/2013</StartDate> 
     <RateAmount>10</RateAmount> 
     <Discount>-2</Discount> 
    </Rate> 
    <Rate> 
     <NoOfMonths>1</NoOfMonths> 
     <StartDate>15/06/2013</StartDate> 
     <RateAmount>10</RateAmount> 
     <Discount>-5</Discount> 
    </Rate> 
</RateList> 

有人可以幫忙嗎?我如何選擇/計數只有直接兄弟姐妹?

謝謝!

+0

你可以使用XSLT 2.0嗎? – 2013-05-13 00:42:24

+0

不幸的是,沒有:( – elefant 2013-05-13 00:45:11

回答

1

試試這個(有些解釋在XSLT評論):

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/"> 
     <RateList> 
      <xsl:apply-templates select="*/ROW"/> 
     </RateList> 
    </xsl:template> 
    <xsl:template match="ROW"> 

     <!--Look for preceding row which has not the same data (RATE_AMOUNT and DISCOUNT) as the current. 
     And generate a id, here month concatenated with an '#'.--> 
     <xsl:variable name="notSameData" 
        select="concat(preceding-sibling::ROW 
         [not(RATE_AMOUNT=current()/RATE_AMOUNT 
         and DISCOUNT=current()/DISCOUNT)][1]/MONTH,'#')"/> 

     <!--Count following month which has same data as current 
     and also the same preceding month with not the same data as the current--> 
     <xsl:variable name="noOfMonths" 
         select="count(following-sibling::* 
          [ RATE_AMOUNT=preceding-sibling::*[1]/RATE_AMOUNT and 
           DISCOUNT = preceding-sibling::*[1]/DISCOUNT] 
          [ 
            concat(preceding-sibling::ROW 
            [not(RATE_AMOUNT=current()/RATE_AMOUNT 
            and DISCOUNT=current()/DISCOUNT)][1]/MONTH,'#') = $notSameData 
          ]) +1 "/> 

     <!--Output only for rows which don not have a not a direct (first) preceding one with same data.--> 
     <xsl:if test="not(preceding-sibling::ROW[1][RATE_AMOUNT=current()/RATE_AMOUNT][DISCOUNT=current()/DISCOUNT])"> 
       <Rate> 
       <NoOfMonths> 
        <xsl:value-of select="$noOfMonths"/> 
       </NoOfMonths> 
       <StartDate> 
        <xsl:value-of select="START_DATE"/> 
       </StartDate> 
       <RateAmount> 
        <xsl:value-of select="RATE_AMOUNT"/> 
       </RateAmount> 
       <Discount> 
        <xsl:value-of select="DISCOUNT"/> 
       </Discount> 
      </Rate> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

將產生以下輸出:

<?xml version="1.0"?> 
<RateList> 
    <Rate> 
    <NoOfMonths>2</NoOfMonths> 
    <StartDate>15/04/2013</StartDate> 
    <RateAmount>10</RateAmount> 
    <Discount>-2</Discount> 
    </Rate> 
    <Rate> 
    <NoOfMonths>1</NoOfMonths> 
    <StartDate>15/06/2013</StartDate> 
    <RateAmount>10</RateAmount> 
    <Discount>-5</Discount> 
    </Rate> 
    <Rate> 
    <NoOfMonths>1</NoOfMonths> 
    <StartDate>15/07/2013</StartDate> 
    <RateAmount>10</RateAmount> 
    <Discount>-2</Discount> 
    </Rate> 
</RateList> 

評論:我沒有使用xlt:key,因爲我最喜歡的xlst處理器xsltproc不支持xls:key語句中的current()。

+0

謝謝!這是完美的! – elefant 2013-05-13 22:32:58

+0

很高興我可以幫到你能標記答案是有效的嗎?如果你不知道如何看待:http:///stackoverflow.com/faq#howtoask – 2013-05-14 08:14:13

-1

通過直接兄弟姐妹我瞭解兄弟姐妹只是在上面和下面。在這種情況下,您可以使用position()函數進行限制。我剛開始這個學我自己,但它可能是像

following-sibling::*[1] 

preceding-sibling::*[1] 
+0

這不會產生預期的輸出 – 2013-05-13 09:35:59