我正在使用BaseX XQJ API对Java应用程序中的XML文件执行xquery查询。我构建的以下xquery很好地生成了我想要的输出:
let $doc := doc("eprints")
for $i in distinct-values($doc//issn)
let $jn := $doc//paper[issn = $i]/publication
where (count(distinct-values($jn)) > 1)
return <issn num="{$i}">"{$jn}"</issn>
在说服该查询通过在BaseX应用程序中对其进行测试而工作之后,我用Java代码实现了该查询。
public static void main(String[] args) throws XQException{
XQDataSource ds = new BaseXXQDataSource();
ds.setProperty("serverName", "localhost");
ds.setProperty("port", "1984");
ds.setProperty("user", "xxxx");
ds.setProperty("password", "xxxxx");
ds.setProperty("databaseName", "eprints");
XQConnection conn = ds.getConnection("admin", "admin");
XQExpression xqe = conn.createExpression();
XQResultSequence result = xqe.executeQuery("let $doc := doc(\"eprints\")"+
"for $i in distinct-values($doc//issn)"+
"let $jn := $doc//paper[issn = $i]/publication"+
"where (count(distinct-values($jn)) > 1)"+
"return <issn num='{$i}'>'{jn}'</issn>"
);
}
但是,此代码导致错误,指出找不到$ jn变量:
线程“主”中的异常javax.xml.xquery.XQQueryException:[XPST0008]:未定义变量$ jn。查看查询时,可以看到$ jn实际上是在for语句的let语句中定义的。
但是,当我直接插入使用$ jn的分配给$ jn的表达式时,代码可以正常工作:
public static void main(String[] args) throws XQException{
XQDataSource ds = new BaseXXQDataSource();
ds.setProperty("serverName", "localhost");
ds.setProperty("port", "1984");
ds.setProperty("user", "admin");
ds.setProperty("password", "admin");
ds.setProperty("databaseName", "eprints");
XQConnection conn = ds.getConnection("admin", "admin");
XQExpression xqe = conn.createExpression();
XQResultSequence result = xqe.executeQuery("let $doc := doc(\"eprints\")"+
"for $i in distinct-values($doc//issn)"+
"where (count(distinct-values($doc//paper[issn = $i]/publication)) > 1)"+
"return <issn num='{$i}'>'{$doc//paper[issn = $i]/publication}'</issn>"
);
}
似乎BaseX XQJ API无法处理在for语句中具有let语句的查询。有谁知道错误的原因是什么?
最佳答案
原始查询中的publication
和where
之间没有空格(由字符串串联掩盖),因此这两行都被解释为轴路径和动态函数应用程序:
let $jn := $doc//paper[issn = $i]/publicationwhere (count(distinct-values($jn)) > 1)
由于不允许使用递归变量定义,因此会产生错误。只需在
publication
之后插入一个空格,即可正常运行。