如何在XSLT中保留行节点计算结果并用于合计以解决舍入误差
基于行计算结果累加合计以消除XSLT舍入误差
可以通过先保留每行计算后的已舍入应税金额(TaxableAmt),再将这些值累加得到合计,完全消除舍入误差。核心思路是先存储每行的计算结果,再对存储值求和,而非直接对原始数据做聚合后舍入。
实现方案
以下是调整后的XSLT代码,通过临时存储每行的舍入结果,再用于合计计算:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"> <xsl:output method="xml" indent="yes"/> <!-- 存储每行计算后的舍入值 --> <xsl:variable name="calculatedItems"> <xsl:for-each select="group/S9/ByAddress/Receipts"> <Item> <xsl:attribute name="TaxableAmt"> <xsl:value-of select="format-number(abs(PaymentAmt div (1 + Tax)), '0.00')"/> </xsl:attribute> <xsl:attribute name="TaxRate"> <xsl:value-of select="format-number(abs(Tax), '0.00')"/> </xsl:attribute> <xsl:attribute name="TaxAmt"> <xsl:value-of select="format-number(abs(PaymentAmt * Tax), '0.00')"/> </xsl:attribute> </Item> </xsl:for-each> </xsl:variable> <!-- 将临时变量转换为可查询的节点集(XSLT 1.0需依赖exsl扩展) --> <xsl:variable name="itemNodes" select="exsl:node-set($calculatedItems)/Item"/> <xsl:template match="/"> <!-- 输出每行的计算结果 --> <Items> <xsl:copy-of select="$itemNodes"/> </Items> <!-- 基于存储的行结果计算合计 --> <Total> <Taxes> <xsl:attribute name="TaxableAmt"> <xsl:value-of select="format-number(sum($itemNodes/@TaxableAmt), '0.00')"/> </xsl:attribute> <xsl:attribute name="TaxRate"> <xsl:value-of select="format-number(abs(group/S9/ByAddress/Receipts[1]/Tax), '0.00')"/> </xsl:attribute> <xsl:attribute name="TaxAmt"> <xsl:value-of select="format-number(sum($itemNodes/@TaxAmt), '0.00')"/> </xsl:attribute> </Taxes> </Total> </xsl:template> </xsl:stylesheet>
关键说明
- 临时存储行结果:使用
<xsl:variable>生成包含每行舍后值的临时节点树,确保合计时使用的是和目标系统完全一致的每行数值。 - 节点集转换:XSLT 1.0中需要借助
exsl:node-set扩展将临时变量转换为可查询的节点集;若使用XSLT 2.0及以上版本,可直接使用变量中的节点,无需转换。 - 合计计算:对存储的
@TaxableAmt属性值求和后再格式化,确保合计结果与目标系统行累加的结果完全一致,消除舍入误差。
内容的提问来源于stack exchange,提问作者Cristiano Oliveira
相关产品推荐
相关产品推荐

