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



我有一个要求,我需要根据不同部分的两个不同值显示差异金额(<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>的section。现在<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>

如果你观察到<ReversalInd>是CR/DR,应该根据最高TotalAmount值来识别。

我已经应用了下面的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>

尝试以下基于Muenchian分组的解决方案。TXLifeRequest按FundCode和AccountNumber分组。

即使组中有两个以上的条目也可以工作。组输出(特别是ReversalInd)的所有数据都来自TotalAmount最高的那个。TotalAmount的值为第一个(最高)TotalAmount与其余的TotalAmount之差。

它也考虑请求:"而且,如果您观察到CR/DR应该基于最高TotalAmount值来识别。"

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>

这是您对这些值求和的解决方案:

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>

相关内容

  • 没有找到相关文章

最新更新