You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Saxon执行XQuery时如何使用XSD中定义的类型解决计算精度问题

问题描述

我有如下XML文档:

<?xml version="1.0" encoding="UTF-8"?>
<root xsi:noNamespaceSchemaLocation="example.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <a>0.1</a>
    <b>0.2</b>
</root>

该文档关联了以下XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="root">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="a" type="xs:decimal"/>
                <xs:element name="b" type="xs:decimal"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

我使用如下代码片段执行XQuery表达式 let $a := /root/a, $b := /root/b, $res := $a + $b return $res:

var proc = new Processor(false);

var builder = proc.newDocumentBuilder();
builder.setBaseURI(URI.create("http://test.ru"));

var file = new File(filePath);
var doc = builder.build(file);

var expression = "let $a := /root/a, $b := /root/b, $res := $a + $b return $res";

var compiler = proc.newXQueryCompiler();
var executable = compiler.compile(expression);
var selector = executable.load();
selector.setContextItem(doc);

return selector.evaluate();

运行结果为 0.30000000000000004,该误差是默认采用number/xs:double类型导致的。
但我的XSD中已定义元素a和b为xs:decimal类型,有没有办法让Saxon在执行XQuery表达式时调用XSD中定义的类型?


更新

我已获取SaxonEE试用许可,通过如下代码加载许可:

var conf = new com.saxonica.config.EnterpriseConfiguration();
conf.setConfigurationProperty(Feature.LICENSE_FILE_LOCATION, "/path/to/saxon-license.lic");

var proc = new Processor(conf);

我仍使用相同的XML文档和XSD,同时在XQuery表达式的序言部分添加了import schema语句:

import schema default element namespace "" at "/path/to/example.xsd";
let $a := /root/a, $b := /root/b, $res := $a + $b return $res

但运行结果仍然是0.30000000000000004,请问我的操作哪里存在问题?


更新2

结合所有建议,以下是使用Saxon-EE实现模式感知XQuery查询的可运行示例:

var conf = new com.saxonica.config.EnterpriseConfiguration();
conf.setConfigurationProperty(Feature.LICENSE_FILE_LOCATION, "/path/to/saxon-license.lic");
conf.setSchemaValidationMode(net.sf.saxon.lib.Validation.STRICT);

var proc = new Processor(conf);

var schemaManager = proc.getSchemaManager();
var source = new SAXSource(new InputSource("/path/to/example.xsd"));
schemaManager.load(source);

var builder = proc.newDocumentBuilder();
builder.setBaseURI(URI.create("http://test.ru"));

var file = new File(filePath);
var doc = builder.build(file);

var prolog = "import schema default element namespace \"\" at \"/path/to/example.xsd\";"
var expression = prolog + "let $a := /root/a, $b := /root/b, $res := $a + $b return $res";

var compiler = proc.newXQueryCompiler();
var executable = compiler.compile(expression);
var selector = executable.load();
selector.setContextItem(doc);

return selector.evaluate();

问题原因与解决方案

之前运行结果不符合预期,是因为缺失两个必要配置:

  • 默认情况下Saxon解析XML文档仅读取节点文本内容,不会自动触发XSD校验,也不会给节点附加XSD中定义的类型信息,运算时会默认将文本转为xs:double类型计算,自然会出现浮点数精度误差。
  • 仅在XQuery头部添加import schema仅能让查询编译器识别类型定义,需要提前将XSD加载到Saxon的SchemaManager中,同时开启XML文档的严格校验模式,才能在解析XML时给对应节点打上xs:decimal的类型标记。

你最后给出的更新2的代码已经补全了所有必要配置,运行后会按照xs:decimal规则执行加法运算,得到正确结果0.3。


内容的提问来源于stack exchange,提问作者Dmitriy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 05:24:03