Мне нужно XSLT-преобразование, которое разделяет узлы на основе сравнения между дочерними узлами и в результате выполняет вычисления - PullRequest
1 голос
/ 24 июня 2010

Это немного сложно, и я действительно не сейчас, если это возможно. Я получил этот XML:

<XML>
<member>
    <InicialAmount>10000000</InitialAmount>
    <Flows>
        <Payment>
            <Date>20100621</Date>
            <Period>
                <Amount>10000000</Amount>
                <StartDate>20100521</StartDate>
                <EndDate>20100621</EndDate>
                <contribution>
                    <contributionFlow>
                        <Amount>10000000</Amount>
                        <StartDate>20100521</StartDate>
                        <EndDate>20100621</EndDate>
                    </contributionFlow>
                </contribution>
            </Period>
        </Payment>
        <Payment>
            <Date>20100823</Date>
            <Period>
                <Amount>9000000</Amount>
                <StartDate>20100621</StartDate>
                <EndDate>20100921</EndDate>
                <contribution>
                    <contributionFlow>
                        <Amount>9000000</Amount>
                        <StartDate>20100621</StartDate>
                        <EndDate>20100721</EndDate>
                    </contributionFlow>
                    <contributionFlow>
                        <Amount>8000000</Amount>
                        <StartDate>20100721</StartDate>
                        <EndDate>20100823</EndDate>
                    </contributionFlow>
                </contribution>
            </Period>
        </Payment>
    </Flows>
</member>

И мне нужно сделать преобразование (или более одного, если необходимо), которое даст мне следующее:

<XML>
<Flows>
    <Flow>
        <PaymentDate>20100621</PaymentDate>
        <StartDate>20100521</StartDate>
        <EndDate>20100621</EndDate>
        <EventType>C</EventType>
    </Flow>
    <Flow>
        <PaymentDate>20100823</PaymentDate>
        <StartDate>20100621</StartDate>
        <EndDate>20100721</EndDate>
        <EventType>A</EventType>
        <AmortizationPercent>10.0</AmortizationPercent>
    </Flow>
    <Flow>
        <PaymentDate>20100823</PaymentDate>
        <StartDate>20100721</StartDate>
        <EndDate>20100823</EndDate>
        <EventType>A</EventType>
        <AmortizationPercent>10.0</AmortizationPercent>
    </Flow>
</Flows>

Это возможно?

Мне нужно отсортировать каждый <contributionFlow> (который впоследствии будет переименован в <Flow>) в одну из двух категорий в соответствии с критериями.

Не просто сортировка, на самом деле, мне нужно внести изменения в макет, удалив поле (<Amount>) и скопировав другое из родительского узла (<Date> из <Payment>, которое должно вызвать <PaymentDate> в новый).

Кроме того, мне нужно создать поле <EventType>, которое должно быть заполнено информацией, основанной на категории, в которую помещается <contributionFlow>. Но чтобы выяснить, в какой категории находится узел, мне нужно сделать расчет.

Мне нужно проверить и посмотреть, отличается ли поле <Amount> от того же поля, что и поле <contributionFlow> до этого (во-первых, если поле отличается от поля <InicialAmount>). Если это так, <EventType> должен быть заполнен буквой A, если нет - C.

Более того, если <EventType> окажется A, необходимо выполнить расчет для заполнения узла <AmortizationPercent>.

Значение в <AmortizationPercent> определяется как разница между <Amount> значением предыдущего и текущего <contributionFlow>, деленная на <InicialAmount>, все это время 100.0.

Я действительно даже не знаю, возможно ли это в XSLT-преобразовании, но на данный момент это единственный способ, которым я могу заставить свою систему делать такие вещи, и это то, что мне нужно сделать. Я только начинаю изучать XSLT, поэтому мне трудно найти решения для себя.

1 Ответ

2 голосов
/ 24 июня 2010

Это не так уж сложно ...:)

Это преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vInitAm" select="/*/InitialAmount"/>
 <xsl:template match="node()|@*">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="*[not(self::Flows or self::contributionFlow) and .//contributionFlow]">
   <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match=
   "Period/*[not(.//contributionFlow)] | Payment/*[not(.//contributionFlow)]"/>

 <xsl:template match="Amount|InitialAmount"/>

 <xsl:template match="contributionFlow">
   <Flow>
     <PaymentDate><xsl:value-of select="../../../Date"/></PaymentDate>
     <xsl:apply-templates/>
     <xsl:variable name="vPrevAmount" select=
      "(preceding::contributionFlow[1]/Amount
      |
       $vInitAm
       )
        [last()]"/>
    <xsl:variable name="vEvType" select=
     "substring('CA', 1 + not(Amount = $vPrevAmount), 1)"/>

     <EventType><xsl:value-of select="$vEvType"/></EventType>

     <xsl:if test="$vEvType = 'A'">
       <AmortizationPercent>
         <xsl:value-of select="($vPrevAmount - Amount)*100 div $vInitAm"/>
       </AmortizationPercent>
     </xsl:if>
   </Flow>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML (исправлено, чтобы быть правильно сформированным):

<member>
    <InitialAmount>10000000</InitialAmount>
    <Flows>
        <Payment>
            <Date>20100621</Date>
            <Period>
                <Amount>10000000</Amount>
                <StartDate>20100521</StartDate>
                <EndDate>20100621</EndDate>
                <contribution>
                    <contributionFlow>
                        <Amount>10000000</Amount>
                        <StartDate>20100521</StartDate>
                        <EndDate>20100621</EndDate>
                    </contributionFlow>
                </contribution>
            </Period>
        </Payment>
        <Payment>
            <Date>20100823</Date>
            <Period>
                <Amount>9000000</Amount>
                <StartDate>20100621</StartDate>
                <EndDate>20100921</EndDate>
                <contribution>
                    <contributionFlow>
                        <Amount>9000000</Amount>
                        <StartDate>20100621</StartDate>
                        <EndDate>20100721</EndDate>
                    </contributionFlow>
                    <contributionFlow>
                        <Amount>8000000</Amount>
                        <StartDate>20100721</StartDate>
                        <EndDate>20100823</EndDate>
                    </contributionFlow>
                </contribution>
            </Period>
        </Payment>
    </Flows>
</member>

дает требуемый, правильный результат :

<Flows>
    <Flow>
        <PaymentDate>20100621</PaymentDate>
        <StartDate>20100521</StartDate>
        <EndDate>20100621</EndDate>
        <EventType>C</EventType>
    </Flow>
    <Flow>
        <PaymentDate>20100823</PaymentDate>
        <StartDate>20100621</StartDate>
        <EndDate>20100721</EndDate>
        <EventType>A</EventType>
        <AmortizationPercent>10</AmortizationPercent>
    </Flow>
    <Flow>
        <PaymentDate>20100823</PaymentDate>
        <StartDate>20100721</StartDate>
        <EndDate>20100823</EndDate>
        <EventType>A</EventType>
        <AmortizationPercent>10</AmortizationPercent>
    </Flow>
</Flows>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...