SaxonApiException:提供的节点已经过模式验证,但 XPath 表达式是在没有模式感知的情况下编译的
SaxonApiException: The supplied node has been schema-validated, but the XPath expression was compiled without schema-awareness
我刚刚从 Saxon EE 9.6.0.4 升级到 9.8.0.12,现在在以下代码中,我在调用 setContextItem()
时遇到异常
XPathExecutable exe = xPath.compile(query);
XPathSelector selector = exe.load();
selector.setContextItem(xmlDocument);
我创建 xpath 对象如下:
void ctor(InputStream xmlData, InputStream schemaFile, boolean preserveWhiteSpace) throws SAXException, SchemaException, SaxonApiException {
this.rootNode = new XpathDataSourceNode();
Map xsdNamespaces = new HashMap();
XMLReader reader = XMLReaderFactory.createXMLReader();
//reader.setEntityResolver(runtime.);
InputSource xmlSource = new InputSource(xmlData);
SAXSource saxSource = new SAXSource(reader, xmlSource);
Source schemaSource = new StreamSource(schemaFile);
Configuration config = createEnterpriseConfiguration();
config.addSchemaSource(schemaSource);
Processor processor = new Processor(config);
SchemaValidator validator = new SchemaValidatorImpl(processor);
DocumentBuilder doc_builder = processor.newDocumentBuilder();
if(!preserveWhiteSpace)
doc_builder.setWhitespaceStrippingPolicy(WhitespaceStrippingPolicy.ALL);
doc_builder.setSchemaValidator(validator);
XdmNode root_node = doc_builder.build(saxSource);
XPathCompiler compiler = processor.newXPathCompiler();
declareNameSpaces(root_node, compiler);
this.xmlRootNode = root_node;
this.xPath = compiler;
在这种情况下我需要做些什么不同的事情?
谢谢 - 戴夫
您需要设置
compiler.SchemaAware = true;
引入检查(和错误消息)是因为早期版本在这种情况下会产生不正确的结果:SchemaAware
属性 设置为 false,优化器假定所有原子化内容都将xs:untypedAtomic
,如果输入文档已通过模式验证,则该值不正确。更改优化器以消除此假设会导致所有非模式感知 XPath 用户(即大多数用户)的性能下降。
请注意,如果您打算使用 XPath 查询类型化数据,那么最好 XPath 编译器可以访问该架构,这样它实际上可以利用数据类型化这一事实。但是,这样做的范围是有限的,因为 XPath API 没有等同于 XQuery 中的 XQueryCompiler.ContextItemType
属性,后者允许静态声明上下文项的类型。所以在实践中,XPath 编译器将无法根据模式信息进行许多静态推断(或检测许多错误)。
我刚刚从 Saxon EE 9.6.0.4 升级到 9.8.0.12,现在在以下代码中,我在调用 setContextItem()
时遇到异常XPathExecutable exe = xPath.compile(query);
XPathSelector selector = exe.load();
selector.setContextItem(xmlDocument);
我创建 xpath 对象如下:
void ctor(InputStream xmlData, InputStream schemaFile, boolean preserveWhiteSpace) throws SAXException, SchemaException, SaxonApiException {
this.rootNode = new XpathDataSourceNode();
Map xsdNamespaces = new HashMap();
XMLReader reader = XMLReaderFactory.createXMLReader();
//reader.setEntityResolver(runtime.);
InputSource xmlSource = new InputSource(xmlData);
SAXSource saxSource = new SAXSource(reader, xmlSource);
Source schemaSource = new StreamSource(schemaFile);
Configuration config = createEnterpriseConfiguration();
config.addSchemaSource(schemaSource);
Processor processor = new Processor(config);
SchemaValidator validator = new SchemaValidatorImpl(processor);
DocumentBuilder doc_builder = processor.newDocumentBuilder();
if(!preserveWhiteSpace)
doc_builder.setWhitespaceStrippingPolicy(WhitespaceStrippingPolicy.ALL);
doc_builder.setSchemaValidator(validator);
XdmNode root_node = doc_builder.build(saxSource);
XPathCompiler compiler = processor.newXPathCompiler();
declareNameSpaces(root_node, compiler);
this.xmlRootNode = root_node;
this.xPath = compiler;
在这种情况下我需要做些什么不同的事情?
谢谢 - 戴夫
您需要设置
compiler.SchemaAware = true;
引入检查(和错误消息)是因为早期版本在这种情况下会产生不正确的结果:SchemaAware
属性 设置为 false,优化器假定所有原子化内容都将xs:untypedAtomic
,如果输入文档已通过模式验证,则该值不正确。更改优化器以消除此假设会导致所有非模式感知 XPath 用户(即大多数用户)的性能下降。
请注意,如果您打算使用 XPath 查询类型化数据,那么最好 XPath 编译器可以访问该架构,这样它实际上可以利用数据类型化这一事实。但是,这样做的范围是有限的,因为 XPath API 没有等同于 XQuery 中的 XQueryCompiler.ContextItemType
属性,后者允许静态声明上下文项的类型。所以在实践中,XPath 编译器将无法根据模式信息进行许多静态推断(或检测许多错误)。