xslt比较两个不同的节点然后合并

时间:2013-05-15 08:23:46

标签: xslt xslt-1.0

我有一个要求,我需要根据不同部分中的两个不同的值显示差异量(<TotalAmount>)。输入xml如下。

 <TXLife xmlns="http://ACORD.org/Standards/Life/2">
    <TXLifeRequest>
        <FundCode>LTRW00</FundCode>
        <AccountNumber>34142</AccountNumber>
        <ReversalInd>Cr</ReversalInd>
        <TotalAmount>1600</TotalAmount>
    </TXLifeRequest>
    <TXLifeRequest>
        <FundCode>LTRW00</FundCode>
        <AccountNumber>34142</AccountNumber>
        <ReversalInd>Dr</ReversalInd>
        <TotalAmount>350</TotalAmount>
    </TXLifeRequest>
    <TXLifeRequest>
        <FundCode>LUL500</FundCode>
        <AccountNumber>34142</AccountNumber>
        <ReversalInd>Cr</ReversalInd>
        <TotalAmount>500</TotalAmount>
    </TXLifeRequest>
    <TXLifeRequest>
        <FundCode>LUL500</FundCode>
        <AccountNumber>34142</AccountNumber>
        <ReversalInd>Dr</ReversalInd>
        <TotalAmount>800</TotalAmount>
    </TXLifeRequest>    
</TXLife>

从上面的xml中,找到差异金额的条件是<FundCode><AccountNumber>。  如果任何具有相同<FundCode><AccountNumber>的部分检索<TotalAmount>并找到差异。

例如来自上面的xml: -

LTRW00和34142有两个部分<fundcode><Accountnumber>相同。 现在<TotalAmount>的差异是1250(1600 - 250)。我还需要在其他部分重复这个逻辑。

所以最终输出xml应该是这样的:

 <TXLife xmlns="http://ACORD.org/Standards/Life/2">
        <TXLifeRequest>
            <FundCode>LTRW00</FundCode>
            <AccountNumber>34142</AccountNumber>
            <ReversalInd>Cr</ReversalInd>
            <TotalAmount>1250</TotalAmount>
        </TXLifeRequest>
        <TXLifeRequest>
            <FundCode>LUL500</FundCode>
            <AccountNumber>34142</AccountNumber>
            <ReversalInd>Dr</ReversalInd>
            <TotalAmount>300</TotalAmount>
        </TXLifeRequest>    
    </TXLife>

此外,如果您发现应根据最高TotalAmount值识别CR {DR <ReversalInd>

我已经应用了下面的xslt但没有输出。任何想法如何在xslt 1.0中实现。非常感谢。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0" xmlns:ns="http://ACORD.org/Standards/Life/2">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="/ns:TXLife/ns:TXLifeRequest">
        <xsl:element name="TXLife" namespace="http://ACORD.org/Standards/Life/2">
           <xsl:call-template name="balance">
               <xsl:with-param name="total" select="ns:TotalAmount"></xsl:with-param>
           </xsl:call-template>
            <xsl:copy-of select="."/>
        </xsl:element>
    </xsl:template>

    <xsl:template name="balance">
        <xsl:param name="total"></xsl:param>
        <xsl:variable name="reminder" select="0"></xsl:variable>        
        <xsl:variable name="val1">
        <xsl:value-of select="$total[1]"/>
        </xsl:variable>
        <xsl:variable name="val2">
        <xsl:value-of select="$total[position() &gt; 1]"/>
        </xsl:variable>

        <xsl:if test="$val1 &gt; $val2">
            <remainingAmount><xsl:value-of select="$val1 - $val2"/></remainingAmount>
        </xsl:if>

    </xsl:template>
</xsl:stylesheet>

2 个答案:

答案 0 :(得分:1)

这是将这些值相加的解决方案:

<强> XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1"
  xmlns:ns="http://ACORD.org/Standards/Life/2">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:key name="Request" match="ns:TXLifeRequest" use="ns:FundCode"/>


  <xsl:template match="ns:TXLife">
    <TXLife>
      <xsl:variable name="result"><xsl:apply-templates
        select="ns:TXLifeRequest[generate-id() = generate-id(key('Request',ns:FundCode))]"/>
      </xsl:variable>
      <xsl:copy-of select="$result"/>
      <TXLifeRequest><xsl:element name="GrandTotal"><xsl:value-of select="sum($result//TotalAmount)"/></xsl:element></TXLifeRequest>
    </TXLife>
  </xsl:template>

  <xsl:template match="ns:TXLifeRequest">
    <TXLifeRequest>
      <xsl:for-each select="*">
        <xsl:choose>
          <xsl:when test="name()='TotalAmount'">
            <xsl:variable name="currentFundCode" select="preceding-sibling::ns:FundCode"/>
            <xsl:variable name="currentAccountNumber" select="preceding-sibling::ns:AccountNumber"/>
            <xsl:variable name="amountToBeDeduct"
              select="parent::ns:TXLifeRequest/following-sibling::ns:TXLifeRequest[ns:FundCode=$currentFundCode and ns:AccountNumber=$currentAccountNumber]/ns:TotalAmount/text()"/>
            <xsl:variable name="actualAmt" select=". - $amountToBeDeduct"/>
            <xsl:element name="{name()}">
              <xsl:choose>
                <xsl:when test="starts-with($actualAmt,'-')">
                  <xsl:value-of select="substring-after($actualAmt,'-')"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="$actualAmt"/>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:element>
          </xsl:when>
          <xsl:otherwise>
            <xsl:element name="{name()}">
              <xsl:value-of select="."/>
            </xsl:element>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each>
    </TXLifeRequest>
  </xsl:template>


</xsl:stylesheet>

<强>输出:

<TXLife xmlns:ns="http://ACORD.org/Standards/Life/2">
   <TXLifeRequest>
      <FundCode>LTRW00</FundCode>
      <AccountNumber>34142</AccountNumber>
      <ReversalInd>Cr</ReversalInd>
      <TotalAmount>1250</TotalAmount>
   </TXLifeRequest>
   <TXLifeRequest>
      <FundCode>LUL500</FundCode>
      <AccountNumber>34142</AccountNumber>
      <ReversalInd>Cr</ReversalInd>
      <TotalAmount>300</TotalAmount>
   </TXLifeRequest>
   <TXLifeRequest>
      <GrandTotal>1550</GrandTotal>
   </TXLifeRequest>
</TXLife>

答案 1 :(得分:1)

根据 Muenchian分组尝试以下解决方案。 TXLifeRequest按FundCode和AccountNumber分组。

即使组中有两个以上的条目,也会大喊大叫。组输出的所有数据(特别是ReversalInd)来自具有最高TotalAmount的数据。 TotalAmount的值是第一个(最高)TotalAmount和剩余的TotalAmount之差。

它还考虑了这个要求:  &#34;如果您发现CR / DR应该根据最高的TotalAmount值进行识别。&#34;

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

    <xsl:key name="kTXLifeRequest" match="ns:TXLifeRequest" use="concat(ns:FundCode,'#',ns:AccountNumber)"/>

    <xsl:template match="node()|@*">

        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/*">
        <xsl:copy>

            <xsl:for-each select=
                 "ns:TXLifeRequest[generate-id() = generate-id(key('kTXLifeRequest',concat(ns:FundCode,'#',ns:AccountNumber))[1])]" >
                <xsl:copy>
                    <xsl:variable name="group"
                                  select="key('kTXLifeRequest',concat(current()/ns:FundCode,'#',current()/ns:AccountNumber))" />
                    <xsl:for-each select= "$group" >
                        <xsl:sort select="ns:TotalAmount" data-type="number" order="descending"/>
                        <xsl:if test="position() = 1">
                            <xsl:apply-templates select="*[local-name() != 'TotalAmount']" />
                            <TotalAmount>
                                <xsl:value-of select="ns:TotalAmount -  sum($group/ns:TotalAmount)+ ns:TotalAmount" />
                            </TotalAmount>
                        </xsl:if>
                    </xsl:for-each>
                </xsl:copy>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

将生成以下输出:

<TXLife xmlns="http://ACORD.org/Standards/Life/2">
  <TXLifeRequest>
    <FundCode>LTRW00</FundCode>
    <AccountNumber>34142</AccountNumber>
    <ReversalInd>Cr</ReversalInd>
    <TotalAmount xmlns="">1250</TotalAmount>
  </TXLifeRequest>
  <TXLifeRequest>
    <FundCode>LUL500</FundCode>
    <AccountNumber>34142</AccountNumber>
    <ReversalInd>Dr</ReversalInd>
    <TotalAmount xmlns="">300</TotalAmount>
  </TXLifeRequest>
</TXLife>

更新计算GrandTotal的其他请求:

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

    <xsl:key name="kTXLifeRequest" match="ns:TXLifeRequest" use="concat(ns:FundCode,'#',ns:AccountNumber)" />

    <xsl:template match="node()|@*">

        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/*">
        <xsl:copy>
            <xsl:for-each select=
                 "ns:TXLifeRequest[generate-id() = generate-id(key('kTXLifeRequest',concat(ns:FundCode,'#',ns:AccountNumber))[1])]" >
                <xsl:copy>
                    <xsl:variable name="group"
                                  select="key('kTXLifeRequest',concat(current()/ns:FundCode,'#',current()/ns:AccountNumber))" />
                    <xsl:for-each select= "$group" >
                        <xsl:sort select="ns:TotalAmount" data-type="number" order="descending"/>
                        <xsl:if test="position() = 1">

                            <xsl:apply-templates select="*[local-name() != 'TotalAmount']" />
                            <TotalAmount>
                                <xsl:value-of select="ns:TotalAmount -  sum($group/ns:TotalAmount)+ ns:TotalAmount" />
                            </TotalAmount>
                        </xsl:if>
                    </xsl:for-each>
                </xsl:copy>

            </xsl:for-each>
            <GrandTotal>
                <xsl:call-template name="totalSum">
                    <xsl:with-param name="groups"
                        select=
                        "ns:TXLifeRequest[generate-id() = generate-id(key('kTXLifeRequest',concat(ns:FundCode,'#',ns:AccountNumber))[1])]" />
            </xsl:call-template>
            </GrandTotal>
        </xsl:copy>
    </xsl:template>

    <xsl:template name="totalSum">
        <xsl:param name="groups" />
        <xsl:param name="gpos" select="1"/>
        <xsl:param name="sum" select="0" />
        <xsl:choose>
            <xsl:when test="$gpos &lt;= count($groups)" >
                    <xsl:variable name="group"
                                  select="key('kTXLifeRequest',concat($groups[$gpos]/ns:FundCode,'#',$groups[$gpos]/ns:AccountNumber))" />
                    <xsl:for-each select= "$group" >
                        <xsl:sort select="ns:TotalAmount" data-type="number" order="descending"/>
                        <xsl:if test="position() = 1">
                            <xsl:variable name="actTotal" select="ns:TotalAmount -  sum($group/ns:TotalAmount)+ ns:TotalAmount" />
                            <xsl:call-template name="totalSum">
                                <xsl:with-param name="groups" select="$groups" />
                                <xsl:with-param name ="gpos" select="$gpos + 1" />
                                <xsl:with-param name="sum" select="$sum + $actTotal" />
                            </xsl:call-template>
                        </xsl:if>
                    </xsl:for-each>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$sum"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>
相关问题