请求协助实现XSLT 1.0中总金额与子金额的冲抵逻辑
XSLT 1.0 金额冲抵逻辑实现
需要实现XSLT 1.0中的金额冲抵逻辑:利用<header>节点的TotalAmount值,依次冲抵<List>下每个<info>节点的childAmount1、childAmount2,当TotalAmount变为0时立即终止后续处理,未被处理的节点金额保持原值。
具体冲抵规则
规则1(处理childAmount1)
if (childAmount1>0 and TotalAmount>0) { if TotalAmount>=childAmount1 { TotalAmount=TotalAmount-childAmount1 childAmount1=0 } else { childAmount1=childAmount1 - TotalAmount TotalAmount=0 exit the loop } } else exit loop
规则2(处理childAmount2)
if (childAmount2>0 and TotalAmount>0) { if TotalAmount>=childAmount2 { TotalAmount=TotalAmount - childAmount2 childAmount2=0 } else { childAmount2=childAmount2 - TotalAmount TotalAmount=0 exit the loop } } else exit loop
输入示例
<header> <TotalAmount>60</TotalAmount> <List> <info> <serialNo>1</serialNo> <childAmount1>20</childAmount1> <childAmount2>10</childAmount2> </info> <info> <serialNo>2</serialNo> <childAmount1>20</childAmount1> <childAmount2>10</childAmount2> </info> <info> <serialNo>3</serialNo> <childAmount1>20</childAmount1> <childAmount2>10</childAmount2> </info> </List> </header>
输出示例
<header> <TotalAmount>60</TotalAmount> <List> <info> <serialNo>1</serialNo> <childAmount1>0</childAmount1> <childAmount2>0</childAmount2> </info> <info> <serialNo>2</serialNo> <childAmount1>0</childAmount1> <childAmount2>0</childAmount2> </info> <info> <serialNo>3</serialNo> <childAmount1>20</childAmount1> <childAmount2>10</childAmount2> </info> </List> </header>
实现代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 匹配根节点,初始化剩余金额 --> <xsl:template match="/header"> <header> <xsl:copy-of select="TotalAmount"/> <List> <xsl:call-template name="process-info"> <xsl:with-param name="remaining-amount" select="number(TotalAmount)"/> <xsl:with-param name="info-nodes" select="List/info"/> </xsl:call-template> </List> </header> </xsl:template> <!-- 递归处理info节点的模板 --> <xsl:template name="process-info"> <xsl:param name="remaining-amount"/> <xsl:param name="info-nodes"/> <xsl:if test="$info-nodes and $remaining-amount > 0"> <xsl:variable name="current-info" select="$info-nodes[1]"/> <xsl:variable name="ca1" select="number($current-info/childAmount1)"/> <xsl:variable name="ca2" select="number($current-info/childAmount2)"/> <!-- 处理childAmount1 --> <xsl:variable name="after-ca1-amount"> <xsl:choose> <xsl:when test="$ca1 > 0 and $remaining-amount > 0"> <xsl:choose> <xsl:when test="$remaining-amount >= $ca1"> <xsl:value-of select="$remaining-amount - $ca1"/> </xsl:when> <xsl:otherwise>0</xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise><xsl:value-of select="$remaining-amount"/></xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="new-ca1"> <xsl:choose> <xsl:when test="$ca1 > 0 and $remaining-amount > 0"> <xsl:choose> <xsl:when test="$remaining-amount >= $ca1">0</xsl:when> <xsl:otherwise><xsl:value-of select="$ca1 - $remaining-amount"/></xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise><xsl:value-of select="$ca1"/></xsl:otherwise> </xsl:choose> </xsl:variable> <!-- 处理childAmount2,仅当处理完ca1后剩余金额仍大于0时 --> <xsl:variable name="after-ca2-amount"> <xsl:choose> <xsl:when test="$after-ca1-amount > 0 and $ca2 > 0"> <xsl:choose> <xsl:when test="$after-ca1-amount >= $ca2"> <xsl:value-of select="$after-ca1-amount - $ca2"/> </xsl:when> <xsl:otherwise>0</xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise><xsl:value-of select="$after-ca1-amount"/></xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="new-ca2"> <xsl:choose> <xsl:when test="$after-ca1-amount > 0 and $ca2 > 0"> <xsl:choose> <xsl:when test="$after-ca1-amount >= $ca2">0</xsl:when> <xsl:otherwise><xsl:value-of select="$ca2 - $after-ca1-amount"/></xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise><xsl:value-of select="$ca2"/></xsl:otherwise> </xsl:choose> </xsl:variable> <!-- 输出当前处理后的info节点 --> <info> <xsl:copy-of select="$current-info/serialNo"/> <childAmount1><xsl:value-of select="$new-ca1"/></childAmount1> <childAmount2><xsl:value-of select="$new-ca2"/></childAmount2> </info> <!-- 递归处理下一个info节点,传递剩余金额 --> <xsl:call-template name="process-info"> <xsl:with-param name="remaining-amount" select="$after-ca2-amount"/> <xsl:with-param name="info-nodes" select="$info-nodes[position() > 1]"/> </xsl:call-template> </xsl:if> <!-- 输出未处理的info节点(当剩余金额为0时) --> <xsl:if test="$info-nodes and $remaining-amount <= 0"> <xsl:copy-of select="$info-nodes"/> </xsl:if> </xsl:template> <!-- 复制其他未匹配的节点(如果有) --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
代码说明
- 递归模板核心:通过
process-info递归模板传递剩余金额remaining-amount,逐个处理<info>节点,直到金额耗尽或节点处理完毕。 - 金额计算逻辑:严格按照规则先处理
childAmount1,再处理childAmount2,分别计算处理后的金额和剩余金额。 - 终止条件:当剩余金额
remaining-amount≤0时,直接复制剩余未处理的<info>节点,不再进行冲抵计算。 - 节点复制:使用
<xsl:copy-of>保留无需修改的节点(如serialNo),确保输出结构与输入一致。
内容的提问来源于stack exchange,提问作者sum
相关产品推荐
相关产品推荐

