Search code examples
javaxquerysaxon

How to handle multiple values returned by Saxon XQuery processor when one value is undefined?


I am trying to use the Saxon HE XQuery processor in a Java app to perform ad-hoc queries on XML documents.

For example:

for $x in //TestHistory[last()]/results/TestResult
where $x/status = 'TestedFailed'
return (/*/operatorId, 
        $x/status, 
        $x/expectedValue/rawValue, 
        $x/inputValue/rawValue)

Here I am gathering 4 values per hit.

The Java code is

Processor processor = new Processor(false);
XQueryCompiler compiler = processor.newXQueryCompiler();
XQueryExecutable exec = compiler.compile(query.getQuery());
XQueryEvaluator evaluator = exec.load();

XdmNode xmlDoc = processor.newDocumentBuilder().build(file);
evaluator.setSource(xmlDoc.asSource());

XdmValue eval = evaluator.evaluate();

int idx = 0;
int cols = 4;
int rows = eval.size/cols;
String[][] result = new String[rows][cols];

//foreach item in eval fill array

eval contains a simple sequence of XdmItems which I can process - assuming that there are 4 items per row.

However, if the node inputValue/rawValue has not been defined (which is sometimes the case) there is no corresponding XdmItem entry and my processing approach (4 items per row) no longer works.

How can I force each requested attribute to have a corresponding XdmItem in the result?


Solution

  • The "," operator does sequence concatenation, which means empty sequences get lost: the result of ("a", (), "b") is ("a", "b").

    One solution would be to return an array instead of a sequence:

    return [/*/operatorId, 
            $x/status, 
            $x/expectedValue/rawValue, 
            $x/inputValue/rawValue]
    

    You should then be able to cast the result in the Java code to XdmArray, and convert this to a Java list of length 4 using XdmArray.asList()