如何阻止XSLT3.0的xml-to-json()函数将数字转为科学计数法
解决Saxon 9.8 HE中xml-to-json()数字转科学计数法的问题
我之前也碰到过类似的情况,Saxon的xml-to-json()函数在处理较大数字时,默认会触发科学计数法输出,这确实和我们想要保留原数字格式的需求冲突。这里给你两个实用的解决方案:
方案1:将数字转为JSON字符串输出
如果业务场景允许把价格作为字符串类型存储,这是最省心的办法——只需把XML里的<number>元素改成<string>:
<?xml version="1.0" encoding="UTF-8"?> <map xmlns="http://www.w3.org/2005/xpath-functions"> <map key="Request"> <string key="price">1234567</string> </map> </map>
转换后的JSON会是:
{"Request": {"price": "1234567"}}
这种方式完全保留了输入的数字格式,实现成本极低。
方案2:自定义XSLT模板生成JSON(保留数字类型)
如果必须输出JSON数字类型(不带引号),就得绕过xml-to-json()的默认处理逻辑,手动遍历XML结构生成JSON字符串,以此精确控制数字的输出格式。
以下是适配你的map结构的示例XSLT模板:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:map="http://www.w3.org/2005/xpath-functions"> <xsl:output method="text" encoding="UTF-8"/> <!-- 处理根节点map --> <xsl:template match="/map"> <xsl:text>{</xsl:text> <xsl:apply-templates select="*"/> <xsl:text>}</xsl:text> </xsl:template> <!-- 处理嵌套的map元素 --> <xsl:template match="map:map"> <xsl:text>"</xsl:text><xsl:value-of select="@key"/><xsl:text>": {</xsl:text> <xsl:apply-templates select="*"/> <xsl:text>}</xsl:text> <xsl:if test="following-sibling::*">,</xsl:if> </xsl:template> <!-- 处理number元素:用format-number强制普通十进制格式 --> <xsl:template match="map:number"> <xsl:text>"</xsl:text><xsl:value-of select="@key"/><xsl:text>": </xsl:text> <xsl:value-of select="format-number(., '0')"/> <xsl:if test="following-sibling::*">,</xsl:if> </xsl:template> <!-- 可根据需求扩展string、boolean等其他类型的处理模板 --> </xsl:stylesheet>
这个模板会遍历你的XML结构,遇到<number>元素时,用format-number(., '0')把数字格式化为普通十进制形式,彻底避免科学计数法。转换后的JSON会是:
{"Request": {"price": 1234567}}
注意事项
- Saxon 9.8 HE是开源免费版,部分高级配置选项(比如直接控制数字输出格式的参数)并未提供,因此自定义模板是最稳妥的适配方式。
- 如果后续升级到Saxon PE/EE版本,可以查看官方文档是否新增了控制
xml-to-json()数字输出格式的参数,但HE版本还是建议用上述两种方案解决问题。
内容的提问来源于stack exchange,提问作者VSS
相关产品推荐
相关产品推荐

