2013-05-13 5 views
2

Я пытаюсь объединить сразу следующих братьев и сестер с одинаковыми значениями вместе. Но у меня возникают проблемы с выбором только НЕМЕДЛЕННЫХ братьев и сестер.Использование 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? –

+0

К сожалению, нет :( – elefant

ответ

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 не поддерживает current() в операциях xls: key.

+0

Спасибо! Это прекрасно! – elefant

+0

Рад, что я мог помочь. Можете ли вы пометить ответ как действительный? Если вы не знаете, как это выглядит: http: /: /stackoverflow.com/faq#howtoask –

-1

Близким родным братом Я понимаю братьев и сестер чуть выше и ниже. В этом случае вы можете использовать функцию position() для ограничения. Я только начал изучать это сам, но это может быть что-то вроде

following-sibling::*[1] 

и

preceding-sibling::*[1] 
+0

Это не сгенерирует ожидаемый результат –

 Смежные вопросы

  • Нет связанных вопросов^_^