StAX and Pull Parsing

StAX (JSR 173, in the JDK since Java 6) inverts SAX: the program pulls events from an XMLStreamReader in an ordinary loop, keeps state in local variables, and can stop whenever it has what it needs. .NET's XmlReader, PHP's XMLReader and libxml2 3,427 's xmlTextReader (libxml2) work the same way. This one stops at the first sold-out book; the output comes from for api in Dom Sax Stax; do java $api.java booknest-catalog.xml; done:

Stax.java: pulling events and stopping earlyJava
import java.io.FileInputStream;
import javax.xml.stream.*;
public class Stax {
  public static void main(String[] args) throws Exception {
    XMLStreamReader r = XMLInputFactory.newInstance()
        .createXMLStreamReader(new FileInputStream(args[0]));
    double total = 0;
    while (r.hasNext()) {                              // the program pulls each event
      if (r.next() != XMLStreamConstants.START_ELEMENT) continue;
      String name = r.getLocalName();
      if (name.equals("price")) total += Double.parseDouble(r.getElementText());
      if (name.equals("availability") && r.getElementText().equals("out-of-stock")) {
        System.out.println("StAX: sold out at line " + r.getLocation().getLineNumber());
        break;                                         // stop reading: no more parsing work
      }
    }
    System.out.printf("StAX: total %.2f%n", total);
  }
}
Output
DOM:  total 134.74, b3 now in-stock
SAX:  total 134.74
StAX: sold out at line 59
StAX: total 54.49

StAX

The Streaming API for XML (StAX) is a parsing model intermediate between DOM and SAX. Its entry point is a cursor that represents a position within the document. The application moves the cursor forward, "pulling" data from the parser as needed - the opposite of SAX, which "pushes" data to the application by invoking callbacks and requires the application to maintain whatever state is needed to track its position within the document.

Because the application drives iteration explicitly, StAX code can read like an ordinary loop, and the application only needs to keep the state relevant to what it is currently doing - it can stop reading at any point, or skip over uninteresting sections, without processing the whole document. Like SAX, StAX does not build an in-memory document tree, so its memory footprint stays low, but its pull model is generally considered easier to follow than SAX's callback-driven model.

StAX is defined for Java by JSR 173 and has been part of the standard library since Java SE 6, in the javax.xml.stream package. Its two central interfaces are XMLStreamReader, a low-level cursor API, and XMLEventReader, a higher-level API that returns one XMLEvent object per step. StAX is a specific instance of the more general pull parsing pattern.

Full nameStreaming API for XML
Processing modelCursor-based streaming, pull-based
Defined byJSR 173 (Java); part of the standard library since Java SE 6
Key interfacesXMLStreamReader (cursor API), XMLEventReader (iterator API)
ContrastThe application pulls data from the parser, unlike SAX's push model
ch09-stax-cursor.javaJava
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new FileInputStream("books.xml"));

while (reader.hasNext()) {
    int event = reader.next();
    if (event == XMLStreamConstants.START_ELEMENT && reader.getLocalName().equals("book")) {
        System.out.println("Book id: " + reader.getAttributeValue(null, "id"));
    }
}
reader.close();

Pull Parsing

Pull parsing regards an XML document as a series of objects that are read sequentially using the Iterator design pattern: the application explicitly requests, or "pulls", the next parsing event from the parser, rather than the parser calling back into application code. This makes pull parsing compatible with recursive-descent parsers, which mirror the structure of the XML being read.

Because control flow stays with the application code, in an ordinary loop, pull-parsing code is generally easier to understand than SAX parsing code, which is driven by callbacks. StAX in Java and XMLReader in PHP are examples of pull parsers.

PatternIterator design pattern; the application pulls the next event
ContrastOpposite of push-based SAX, where the parser calls back into the application
CompatibilityMaps naturally onto recursive-descent parsers that mirror the XML structure
ExamplesStAX (Java), XMLReader (PHP), XmlReader (.NET)
ch09-pull-xmlreader.phpPHP
<?php
$reader = new XMLReader();
$reader->open('books.xml');

while ($reader->read()) {
    if ($reader->nodeType == XMLReader::ELEMENT && $reader->localName == 'book') {
        echo "Book id: " . $reader->getAttribute('id') . "\n";
    }
}
$reader->close();
?>