Reputation: 841
I'm using BaseX XQJ API to execute xquery queries on XML files within my java application. The following xquery that I constructed nicely generates the output that I want:
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>
After convincing myself that this query works by testing it in the BaseX application, I implemented this query in java code.
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>"
);
}
This code however resulted in a error stating that the $jn variable could not be found: Exception in thread "main" javax.xml.xquery.XQQueryException: [XPST0008]: Undefined variable $jn. When looking at the query one can see that $jn actually is defined in the let-statement within the for-statement.
However, when I directly insert the expression assigned to $jn where $jn was used, the code does work correctly:
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>"
);
}
It seems like the BaseX XQJ API is unable to handle queries which have a let-statement within a for-statement. Does anyone know what the cause of the error is?
Upvotes: 2
Views: 694
Reputation: 4241
There's no space between publication
and where
in your original query (disguised by the string concatenation), so both rows are interpreted as an axis path and a dynamic function application:
let $jn := $doc//paper[issn = $i]/publicationwhere (count(distinct-values($jn)) > 1)
This yields an error because recursive variable definitions aren't allowed. Just insert a space after publication
, then it should run fine.
Upvotes: 3