javaxmlxquerybasexxqj

BaseX XQJ API error on undefined variable, while variable is defined


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?


Solution

  • 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.