我需要一个XSLT转换,它根据子节点之间的比较来分离节点,并进行计算

时间:2010-06-23 20:18:40

标签: xml xslt

这有点复杂,如果可能,我现在真的不会。 我得到了这个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 个答案:

答案 0 :(得分:2)

这真的不太复杂......:)

此转化

<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>