StAX (Streaming API for XML, JSR 173) is Java’s standard pull parser for reading and writing XML, found in the package javax.xml.stream. It has been part of the JDK since Java 6 (the Javadoc for XMLStreamReader says “Since: 1.6”), so on Java 6 or later you normally do not need the Maven artifact javax.xml.stream:stax-api at all. That jar, last released as version 1.0-2 in October 2008, only matters for Java 5 projects, and today it usually turns up as an unwanted transitive dependency that you exclude.
What is the StAX API?
StAX is a Java API for processing XML as a stream. The JSR 173 specification, led by BEA with support from Sun Microsystems, passed its final Java Community Process ballot in March 2004. It sits between the two older XML APIs in Java:
- DOM loads the whole document into a tree in memory. Easy to move around in, but a 500 MB file needs a lot more than 500 MB of heap.
- SAX streams the document and pushes events to your callback methods. Memory use is small, but your code has to track where it is in the document through handler state.
- StAX also streams, but your code pulls the next item when it is ready, in an ordinary loop. You get SAX-level memory use with code that reads top to bottom.
StAX can also write XML (XMLStreamWriter and XMLEventWriter), which SAX cannot.
Cursor API vs event (iterator) API
StAX offers two styles of reading, both created from an XMLInputFactory.
| Point | Cursor API | Event (iterator) API |
|---|---|---|
| Main reader interface | XMLStreamReader | XMLEventReader |
| Writer interface | XMLStreamWriter | XMLEventWriter |
| What next() gives | An int event type; you then query the reader (getLocalName(), getText()) | An XMLEvent object you can keep, pass around or peek at |
| Memory and speed | Lowest overhead, no object per event | Slightly more, one object per event |
| Best for | Fast parsing of large files, performance-critical code | Pipelines and filters that pass events to other code |
The same loop in event style looks like this (it also needs imports for javax.xml.stream.XMLEventReader and javax.xml.stream.events.XMLEvent):
XMLEventReader events = factory.createXMLEventReader(new StringReader(xml));
while (events.hasNext()) {
XMLEvent e = events.nextEvent();
if (e.isStartElement()) {
System.out.println(e.asStartElement().getName().getLocalPart());
}
}StAX vs SAX vs DOM
| Feature | DOM | SAX | StAX |
|---|---|---|---|
| Model | Tree in memory | Push (callbacks) | Pull (your loop) |
| Memory use | Grows with document size | Small, constant | Small, constant |
| Random access / go back | Yes | No | No, forward only |
| Modify the document | Yes | No | No (but can write a new stream) |
| Write XML | Yes, via a Transformer | No | Yes |
| Stop early | Only after full load | Awkward (throw an exception) | Easy, just leave the loop |
| Package | org.w3c.dom, javax.xml.parsers | org.xml.sax, javax.xml.parsers | javax.xml.stream |
| In the JDK since | Java 1.4 (JAXP) | Java 1.4 (JAXP) | Java 6 |
Rule of thumb: DOM for small configuration files you edit, StAX for large or streamed XML such as data feeds, SOAP messages and exports, and SAX mainly in older code that already uses it.
Do you need the stax-api Maven dependency?
If your project runs on Java 6 or later, no. The javax.xml.stream classes ship with the JDK (in the java.xml module from Java 9), along with a working parser implementation. Adding the stax-api jar gives you a second copy of the same interfaces and nothing else.
You will meet the artifact under two sets of coordinates on Maven Central:
| Coordinates | Latest version | Released | Notes |
|---|---|---|---|
| javax.xml.stream:stax-api | 1.0-2 | October 2008 | Sun’s API jar, CDDL / GPL licence; no dependencies |
| stax:stax-api | 1.0.1 | August 2006 | The older Codehaus build, Apache 2.0 licence |
The only case where you would declare it yourself is a legacy project that still has to run on Java 5, which had no StAX in the JDK:
<dependency>
<groupId>javax.xml.stream</groupId>
<artifactId>stax-api</artifactId>
<version>1.0-2</version>
</dependency>On Java 5 you would also need an implementation jar, such as Woodstox, because the API jar holds only interfaces and the factory lookup code.
Why stax-api causes problems
Old libraries written for Java 5 declared stax-api as a dependency, so Maven still pulls it in transitively today. On a modern JDK the duplicate javax.xml.stream classes can lead to class loading conflicts, typically a LinkageError or “loader constraint violation” inside application servers, or split-package errors when the jar ends up on the Java module path. Even when nothing breaks, it is dead weight in your build.
How to find and exclude stax-api in Maven
First find which dependency brings it in:
mvn dependency:tree -Dincludes=javax.xml.stream:stax-api,stax:stax-apiThen add an exclusion under that dependency in pom.xml. Excluding both coordinates covers either variant (the library name here is a placeholder):
<dependency>
<groupId>com.example</groupId>
<artifactId>legacy-xml-lib</artifactId>
<version>2.1.0</version>
<exclusions>
<exclusion>
<groupId>javax.xml.stream</groupId>
<artifactId>stax-api</artifactId>
</exclusion>
<exclusion>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
</exclusion>
</exclusions>
</dependency>Run the build and your tests afterwards. The JDK’s own StAX classes take over, and code that imports javax.xml.stream compiles unchanged. In Gradle the same idea is exclude group: ‘javax.xml.stream’, module: ‘stax-api’.
StAX implementations
The API is a set of interfaces; a parser implementation does the work. XMLInputFactory.newInstance() finds one through a lookup order: the javax.xml.stream.XMLInputFactory system property, then configuration files, then the service loader (a jar on the classpath that registers itself), and finally the JDK’s built-in default.
- JDK built-in parser: derived from Sun’s Java Streaming XML Parser (SJSXP), which Oracle describes as a non-validating, namespace-aware pull parser built on the Xerces2 codebase. It is used when nothing else is configured.
- Woodstox: a widely used open-source implementation of StAX and its extended Stax2 API, often chosen for speed and extra features. Maven coordinates com.fasterxml.woodstox:woodstox-core; the latest release listed on Maven Central is 7.2.2 (August 2026). Adding it is enough for newInstance() to pick it up:
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
<version>7.2.2</version>
</dependency>- Aalto XML: another FasterXML parser implementing StAX, built for high throughput and non-blocking parsing.
StAX example: reading XML with XMLStreamReader
This program reads a small XML string with the cursor API and prints each book’s id, title and price. It needs no Maven dependency on Java 6 or later.
import java.io.StringReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
public class StaxDemo {
public static void main(String[] args) throws XMLStreamException {
String xml = "<library>"
+ "<book id='1'><title>Machine Design</title><price>450</price></book>"
+ "<book id='2'><title>Strength of Materials</title><price>380</price></book>"
+ "</library>";
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(xml));
while (reader.hasNext()) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
String name = reader.getLocalName();
if (name.equals("book")) {
System.out.println("book id=" + reader.getAttributeValue(null, "id"));
} else if (name.equals("title") || name.equals("price")) {
System.out.println(" " + name + ": " + reader.getElementText());
}
}
}
reader.close();
}
}Expected output:
book id=1
title: Machine Design
price: 450
book id=2
title: Strength of Materials
price: 380How it works, step by step:
- The reader starts in the START_DOCUMENT state. Each call to next() moves the cursor to the next event and returns its type as an int constant from XMLStreamConstants.
- On a START_ELEMENT for book, getAttributeValue(null, “id”) reads the id attribute; passing null means “ignore the namespace”.
- On title or price, getElementText() reads all the text up to the matching end tag and leaves the cursor on that END_ELEMENT. It is safer than getText() on CHARACTERS events, because a parser may split long text into several CHARACTERS events.
- The library element starts too, but the code ignores it. After the final end tag the reader reaches END_DOCUMENT, hasNext() returns false and the loop ends.
The XML string has no whitespace between tags, so there are no whitespace-only text events to skip. With a pretty-printed file you would see CHARACTERS events for the line breaks; check reader.isWhiteSpace() or, as here, read text only where you expect it. Markup basics are shared with HTML; see our page on HTML for how tags and attributes work.
Common mistakes with StAX
- Adding stax-api to a Java 8, 11, 17 or 21 project because an old tutorial said so. Remove it.
- Calling getLocalName() on a CHARACTERS event. It throws IllegalStateException; check the event type first.
- Assuming text comes as one event. Use getElementText() or set the factory property XMLInputFactory.IS_COALESCING to true.
- Not closing the reader. XMLStreamReader.close() frees parser resources but does not close the underlying stream or reader, so close that too (try-with-resources on the stream).
- Parsing untrusted XML with default settings. Turn off DTDs and external entities (XMLInputFactory.SUPPORT_DTD set to false) to block XXE attacks.
FAQs
What is stax-api?
stax-api is the Maven artifact (javax.xml.stream:stax-api, latest 1.0-2 from 2008, or the older stax:stax-api 1.0.1) that holds the interfaces of the Streaming API for XML, JSR 173. Since Java 6 the same interfaces are part of the JDK, so the jar is only needed on Java 5.
Is StAX included in the JDK?
Yes. javax.xml.stream has been in Java SE since Java 6, with a built-in parser, and from Java 9 it lives in the java.xml module. You can use XMLInputFactory and XMLStreamReader without adding any dependency.
What is the difference between StAX and SAX?
Both stream XML with low memory use. SAX pushes events to callback methods you register; StAX lets your code pull the next event in a loop, which is easier to read and to stop early. StAX can also write XML; SAX cannot.
How do I exclude stax-api in Maven?
Run mvn dependency:tree to find the dependency that brings it in, then add an exclusions block to that dependency with groupId javax.xml.stream and artifactId stax-api (and stax / stax-api for the older variant).
What is Woodstox?
Woodstox is an open-source, high-performance StAX implementation (Maven: com.fasterxml.woodstox:woodstox-core). With it on the classpath, XMLInputFactory.newInstance() uses Woodstox instead of the JDK’s built-in parser.
