Streaming XQuery results

In the XQJ API you can stream XQuery result sequences and result items via StAX and SAX APIs.

This enables you to process huge amounts of XML data in XQuery result sequence.

If you are unfamiliar with these Streaming APIs and wish to learn how to use them, you can check out a StAX Tutorial and a SAX Tutorial online. This section discusses how to use these APIs within the context of the XQJ API.

There are two important methods on the XQSequence interface, which allow you to A. Create a StAX XMLStreamReader, and B. Stream the content through a SAX ContentHandler.

Take a look at the following interface for XQSequence.

[SNAPSHOT]: XQSequence (Streaming XML content)

public interface XQSequence { // --------------- StAX and SAX METHODS --------------------- // Return Sequence as a StAX Stream Reader to pull data from XMLStreamReader getSequenceAsStream(); // Write Sequence as a set of SAX events void writeSequenceToSAX(ContentHandler saxhdlr); // ---------------------------------------------------------- // Write Sequence to an OutputStream void writeSequence(OutputStream os, Properties props); // Write Sequence to a Writer void writeSequence(Writer ow, Properties props); // Write Sequence to a JAXP/TrAX Result void writeSequenceToResult(Result result); // Other XQSequence methods ... }

Streaming XQuery Result Sequences with StAX

The following is a full working example of streaming XML content via StAX, the query requests all 'book' elements within the document 'books.xml'. Then the entire sequence of 'book' elements can be pulled and streamed sequentially from a StAX XMLStreamReader object.

StAXExample.java

import javax.xml.xquery.*; import net.cfoster.sedna.xqj.SednaXQDataSource; import javax.xml.stream.*; public class StAXExample { public static void main(String[] a) throws XQException, XMLStreamException { XQDataSource xqs = new SednaXQDataSource(); xqs.setProperty("serverName", "localhost"); xqs.setProperty("databaseName", "test"); XQConnection conn = xqs.getConnection("SYSTEM", "MANAGER"); XQExpression xqe = conn.createExpression(); XQResultSequence rs = xqe.executeQuery("doc('books.xml')//book"); XMLStreamReader reader = rs.getSequenceAsStream(); for( ; reader.hasNext() ; reader.next()) System.out.println(getEventString(reader)); // Print tailing END_DOCUMENT event too System.out.println(getEventString(reader)); conn.close(); } static String getEventString(XMLStreamReader reader) { switch(reader.getEventType()) { case XMLStreamConstants.START_ELEMENT: return "START_ELEMENT:\t\"" + reader.getLocalName() + "\""; case XMLStreamConstants.END_ELEMENT: return "END_ELEMENT:\t\"" + reader.getLocalName() + "\""; case XMLStreamConstants.START_DOCUMENT: return "START_DOCUMENT"; case XMLStreamConstants.END_DOCUMENT: return "END_DOCUMENT"; case XMLStreamConstants.CHARACTERS: return "CHARACTERS:\t\"" + reader.getText() + "\""; } return ""; } }

Streaming XQuery Result Sequences with SAX

An alternative way to stream result sequences is with SAX, this pushes XML through a ContentHandler interface which may be suitable for some legacy Java code and applications which do not support pulling data from a StAX reader.

The following is a full working example, which pushes all 'book' elements as events through a SAX ContentHandler implementation.

SAXExample.java

import javax.xml.xquery.*; import net.cfoster.sedna.xqj.SednaXQDataSource; import org.xml.sax.*; import org.xml.sax.helpers.DefaultHandler; public class SAXExample { public static void main(String[] args) throws XQException { XQDataSource xqs = new SednaXQDataSource(); xqs.setProperty("serverName", "localhost"); xqs.setProperty("databaseName", "test"); XQConnection conn = xqs.getConnection("SYSTEM", "MANAGER"); XQExpression xqe = conn.createExpression(); XQResultSequence rs = xqe.executeQuery("doc('books.xml')//book"); rs.writeSequenceToSAX(new MySAXHandler()); conn.close(); } } class MySAXHandler extends DefaultHandler { public void startDocument() { System.out.println("Start Document"); } public void startElement(String u, String name, String qn, Attributes a) { System.out.println("Start Element:\t\"" + name + "\""); } public void endElement(String u, String name, String qn) { System.out.println("End Element:\t\"" + name + "\""); } public void characters(char[] ch, int start, int len) { System.out.println("Characters:\t\""+new String(ch, start, len)+"\""); } public void endDocument() { System.out.println("End Document"); } }

End of tutorial

Congratulations!, you've covered the basics of how to use the XQJ API and are ready to brew some Java with a hint of XQuery, for more detailed information about how to use the XQJ API you can check out the XQJ Specification at the Java Community Process site or the XQJ API Javadocs.

If you find any errors in this tutorial, please contact me.