Apache FOP模板输出值求和异常:无法转换字符串为数值
解决Apache FOP中总价累加时的字符串转double错误
看起来你是在用XSLT配合Apache FOP生成PDF时踩了一个常见的坑——字符串拼接和数值累加搞混了!错误提示里的"50.0060.00"明显是两个价格字符串直接拼在了一起,而不是做数学加法,所以转成double类型时自然失败。下面给你两种针对性的解决方案:
方案1:用XSLT原生sum()函数(最简便)
如果你的XML结构是类似下面这种(Charges下有多个带价格的子节点):
<Charges> <Charge> <Price>50.00</Price> </Charge> <Charge> <Price>60.00</Price> </Charge> </Charges>
完全不需要自己写自定义函数或模板,直接用XSLT内置的sum()函数就能搞定,它会自动把节点文本转成数值并累加,最后用format-number格式化保留两位小数:
<xsl:value-of select="format-number(sum(Charges/Charge/Price), '0.00')" />
这个方法既简洁又不容易出错,优先推荐使用。
方案2:修复自定义模板/扩展函数
如果你必须使用自己写的foo:buildTotalValue函数或getTotalPriceNode模板,核心要做的是把字符串转成数值再累加,而不是直接拼接文本:
修复XSLT模板示例
假设你的getTotalPriceNode模板是递归遍历节点,修改成这样:
<xsl:template name="getTotalPriceNode"> <xsl:param name="chargesNode" /> <!-- 初始化总和为0 --> <xsl:param name="total" select="0" /> <xsl:choose> <!-- 判断是否还有未处理的Charge节点 --> <xsl:when test="$chargesNode/Charge"> <xsl:call-template name="getTotalPriceNode"> <!-- 传递剩下的Charge节点 --> <xsl:with-param name="chargesNode" select="$chargesNode/Charge[position() > 1]" /> <!-- 关键:用number()转成数值后再累加 --> <xsl:with-param name="total" select="$total + number($chargesNode/Charge[1]/Price)" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <!-- 格式化最终结果为两位小数 --> <xsl:value-of select="format-number($total, '0.00')" /> </xsl:otherwise> </xsl:choose> </xsl:template>
修复扩展函数示例(如果是Java扩展)
如果foo:buildTotalValue是Java扩展函数,要确保在遍历节点时先把文本转成Double再累加:
public static String buildTotalValue(Node chargesNode) { double total = 0.0; NodeList chargeNodes = chargesNode.getChildNodes(); for (int i = 0; i < chargeNodes.getLength(); i++) { Node charge = chargeNodes.item(i); if ("Charge".equals(charge.getNodeName())) { // 找到Price节点并转成数值 Node priceNode = charge.getFirstChild(); while (priceNode != null && !"Price".equals(priceNode.getNodeName())) { priceNode = priceNode.getNextSibling(); } if (priceNode != null) { String priceStr = priceNode.getTextContent().trim(); total += Double.parseDouble(priceStr); } } } // 格式化保留两位小数 return String.format("%.2f", total); }
关键排查点
- 检查你的代码是不是在遍历节点时,直接把节点文本和当前总和做了字符串拼接(比如
$total + $priceText,在XSLT里如果$total是字符串就会拼接),而不是先转成数值再相加。 - 如果你加了
<value>节点,要确保是用number($node/value)获取数值,而不是直接取文本内容。 - 确认每个价格节点的文本都是合法的数值格式,没有多余的空格或非数字字符。
内容的提问来源于stack exchange,提问作者Michael Hanrahan
相关产品推荐
相关产品推荐

