Saxon xquery验证失败-需要帮助以了解行为

问题描述

虽然我使用Saxon Java api执行以下xQuery,但我无法理解为什么以下执行/验证失败? (有趣的是,当我在if语句中用and替换or子句时,查询验证成功,但无法理解此行为)

在氧气xml验证器中,当我打开xQuery时,出现NullPointerException-null异常,验证失败。

在Java中,我得到以下区域

java.lang.NullPointerException
    at net.sf.saxon.expr.parser.LoopLifter.markDependencies(LoopLifter.java:168)
    at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:112)

我正在寻找一些专家来帮助我理解以下原因失败的原因。

以下是xQuery,

 
    declare function local:method($input as element(input)) as element(output) 
        {
                <output>
                    <itemADetails>              
                        <service>
                        {
                        for $i in 1 to count($input/*:foo)
                        return
                            for $j in 1 to count($input/*:bar)
                            return
                                if((data($input/*:foo[$i]/*:itemB[1]/*:rangeQualifier)="A") and (data($input/*:foo[$i]/*:serviceId/*:type)="B") ) then
                                    <node></node>
                                else()          
                        }
                        </service>                                          
                    </itemADetails>                                         
                </output>
        };


    declare variable $input as element(input) external;
    local:method($input)

Saxon Verion

implementation 'net.sf.saxon:Saxon-HE:10.2'
implementation 'net.sf.saxon:saxon-xqj:9.1.0.8'

我尝试过的示例代码

 Processor saxon = new Processor(false);
         
        // compile the query
        XQueryCompiler compiler = saxon.newXQueryCompiler();
        XQueryExecutable exec;
       
        ClassLoader classLoader = MessageProcessor.class.getClassLoader();
       
            exec = compiler.compile(new File(classLoader.getResource("Xquery.xqy").getFile()));

Source src = new StreamSource(new StringReader(Files.readString( Paths.get(ClassLoader.getSystemResource(inputfile.xml").toURI()))));
        XdmNode doc = builder.build(src);
 // instantiate the query,bind the input and evaluate
        XQueryEvaluator query = exec.load();
        query.setContextItem(doc);     
 query.setExternalVariable(new QName("input"),doc.select(child("input")).asNode());
   XdmValue result = query.evaluate();
       System.out.println(result.itemAt(0).toString());

当我在Oxygen XML编辑器(使用Saxon-PE XQuery 9.9.1.7引擎)中打开xquery时,无论使用Java代码,都会出现以下验证错误

enter image description here

解决方法

这确实是Saxon优化错误。撒克逊人尝试重写时会发生问题

for $j in 1 to count($input/bar)
return if ($input/foo[$i]/data = 'A' and $input/baz[$i]/type = 'B')
       then <result/>
       else ()

if ($input/foo[$i]/data = 'A' and $input/baz[$i]/type = 'B')
then for $j in 1 to count($input/bar)
     return <result/>
else ()

,您可以通过手工重写来解决此问题。重写的目的是为了防止不必要地重复评估“ if”条件,这种情况在循环中每次都相同。

之所以依赖于“和”条件,是因为撒克逊人将“和”的每个术语视为在循环之外晋升的单独候选者,并且当发现所有这些术语都可以被提升时,它将“和“”部分表达出来,而该错误是在重构过程中发生的。

,

似乎是Saxon中的优化程序错误,我将您的代码缩减为

declare function local:test($input as element(input)) as element(output)
{
  <output>
      <details>
          <service>
          {
              for $i in 1 to count($input/foo)
              return
                  for $j in 1 to count($input/bar)
                  return if ($input/foo[$i]/data = 'A' and $input/baz[$i]/type = 'B')
                         then <result/>
                         else ()
          }
          </service>
      </details>
  </output>
};

declare variable $input as element(input) external := <input>
</input>;

local:test($input)

并且命令行中的Saxon HE 10.2崩溃

java.lang.NullPointerException
        at net.sf.saxon.expr.parser.LoopLifter.markDependencies(LoopLifter.java:168)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:112)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
        at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:101)
        at net.sf.saxon.expr.parser.LoopLifter.process(LoopLifter.java:51)
        at net.sf.saxon.query.XQueryFunction.optimize(XQueryFunction.java:452)
        at net.sf.saxon.query.XQueryFunctionLibrary.optimizeGlobalFunctions(XQueryFunctionLibrary.java:327)
        at net.sf.saxon.query.QueryModule.optimizeGlobalFunctions(QueryModule.java:1207)
        at net.sf.saxon.expr.instruct.Executable.fixupQueryModules(Executable.java:458)
        at net.sf.saxon.query.XQueryParser.makeXQueryExpression(XQueryParser.java:177)
        at net.sf.saxon.query.StaticQueryContext.compileQuery(StaticQueryContext.java:568)
        at net.sf.saxon.query.StaticQueryContext.compileQuery(StaticQueryContext.java:630)
        at net.sf.saxon.s9api.XQueryCompiler.compile(XQueryCompiler.java:609)
        at net.sf.saxon.Query.compileQuery(Query.java:804)
        at net.sf.saxon.Query.doQuery(Query.java:317)
        at net.sf.saxon.Query.main(Query.java:97)
java.lang.NullPointerException

我认为您可以在命令行上使用-opt:0关闭优化,这样上面的代码就不会崩溃。

您可能想在https://saxonica.plan.io/projects/saxon/issues上提出问题,或者等到Saxonica的某人在这里将其提起。

如果我使用

           for $foo at $i in $input/foo
          return
              for $bar at $j in $input/bar

Saxon不会崩溃,因此也许这是一种重写查询的方法,尽管没有数据,但我不确定是否捕获了代码的含义,并且重写与原始代码相同尝试。

,

我用马丁的测试用例(谢谢你,马丁)复制了它:https://saxonica.plan.io/issues/4765

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...