XSLT比较两个不同的节点,然后结合(xslt compare two different node

2019-09-03 06:48发布

我有其中i需要以示区别量(要求<TotalAmount>基于其在不同section.The输入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: -

有具有相同的两个部分<fundcode><Accountnumber>并用LTRW00 34142.现在的差<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应该基于最高总金额值来确定。

我已经申请以下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>

Answer 1:

尝试下面基于Muenchian分组的解决方案。 该TXLifeRequest由FundCode和账户号码分组。

它喊的工作,即使有该组中的两个以上的条目。 所有数据为一组输出(特殊ReversalInd)是从一个具有最高总金额。 总金额的值是所述第一(最高)总金额和剩余的一些差异。

它还考虑请求:“而且,如果你还观察是CR / DR应该确定基于最高总金额价值。”

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>


Answer 2:

这是您的解决方案来总结这些值:

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>

OUTPUT:

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


文章来源: xslt compare two different nodes and then combine
标签: xslt xslt-1.0