mccarthyj
mccarthyj

Reputation: 929

How to use XQuery to output json using Saxon from Java

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?

Upvotes: 5

Views: 1633

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167436

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);

Upvotes: 3

Related Questions