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 编译器将无法根据模式信息进行许多静态推断(或检测许多错误)。