6

I'm using XQuery to convert the XML document below to JSON, using Saxon to process the XQuery file.

<books>
   <book id="book1">
      <author>Book1AuthorSurname, Book1AuthorFirstname</author>
      <title>Book1 Title</title>
      <price>45.00</price>
   </book>
   <book id="book2">
      <author>Book2AuthorSurname, Book2AuthorFirstname</author>
      <title>Book2 Title</title>
      <price>45.00</price>
   </book>
</books>

The XQuery itself is pretty straightforward

xquery version "3.1";

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization"; 
declare namespace map = "http://www.w3.org/2005/xpath-functions/map";

declare option output:method "json";
declare option output:indent "yes";

let $booksXML := doc("books.xml")/books

return array {
  for $book in $booksXML/book
  return map {
   "author": data($book/author),
   "title": data($book/title)
  }
}

and, if I run it from the command line with Saxon, returns correctly

java -cp Saxon-HE-9.8.0-8.jar net.sf.saxon.Query -q:books2json.xqy

 [
   {
    "author":"Book1AuthorSurname, Book1AuthorFirstname",
    "title":"Book1 Title"
   },
   {
    "author":"Book2AuthorSurname, Book2AuthorFirstname",
    "title":"Book2 Title"
   }
 ]

But running it from Java with the following snippet gives a slightly different result

Processor saxon = new Processor(false);
XQueryCompiler compiler = saxon.newXQueryCompiler();
XQueryExecutable exec = compiler.compile(new File("books2json.xqy"));
XQueryEvaluator query = exec.load();
XdmValue result = query.evaluate();
System.out.println(result.toString());

[
    map{"author":"Book1AuthorSurname, Book1AuthorFirstname","title":"Book1 Title"},
    map{"author":"Book2AuthorSurname, Book2AuthorFirstname","title":"Book2 Title"}
]

The "map" in the output from Java is giving an error in a JSON processor that I'm using to read the results, is there a configuration option to remove this from the result?

Joseph McCarthy
  • 897
  • 2
  • 19
  • 41
  • 1
    What kind of final result do you want? Do you simply want a string or a file with the serialized query result, like the command line does? Or do you first want the `XdmValue` and are looking for additional possibilities to then serialize it the way you have it declared in the XQuery code? – Martin Honnen Feb 26 '18 at 14:02
  • yes, just a string as the command line produces – Joseph McCarthy Feb 26 '18 at 14:13

1 Answers1

3

If you want to directly write to System.out respectively any other Destination then you can do it using the run method like this:

    Processor saxon = new Processor(false);
    XQueryCompiler compiler = saxon.newXQueryCompiler();
    XQueryExecutable exec = compiler.compile(new File("query1.xq"));
    XQueryEvaluator query = exec.load(); 

    query.run(saxon.newSerializer(System.out));
    System.out.println();

respectively if you want a String use a Serializer over a StringWriter:

    StringWriter sw = new StringWriter();
    query.run(saxon.newSerializer(sw));
    String result = sw.toString();
    System.out.println(result);
Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • 1
    To expand on this answer, when you use query.evaluate() you are getting the raw result of the query as an XdmValue, not the serialized result: so it is unaffected by any output options in the query. You are then converting the XdmValue to a string using the Java toString() method, which is intended primarily for diagnostic output and not specifically to generate JSON. You get the wanted result when you send the query output to a JSON serializer. – Michael Kay Feb 27 '18 at 08:51