APIClassStylePerformanceBest for
CursorXMLStreamReaderStateful cursor; call next() to advanceHighest — no event object allocationPerformance-critical parsing
IteratorXMLEventReaderReturns XMLEvent objectsSlightly lower — allocates event objectsFiltering, pipelining, cleaner code
import javax.xml.stream.*; import java.io.*; import java.util.*; public class StaxCursorExample { public static List<String> parseTitles(InputStream xml) throws XMLStreamException { List<String> titles = new ArrayList<>(); XMLInputFactory factory = XMLInputFactory.newInstance(); // Disable XXE factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); factory.setProperty(XMLInputFactory.SUPPORT_DTD, false); XMLStreamReader reader = factory.createXMLStreamReader(xml); try { boolean inTitle = false; while (reader.hasNext()) { int event = reader.next(); switch (event) { case XMLStreamConstants.START_ELEMENT -> { inTitle = "title".equals(reader.getLocalName()); if ("book".equals(reader.getLocalName())) { // read attribute String id = reader.getAttributeValue(null, "id"); System.out.println("Found book id=" + id); } } case XMLStreamConstants.CHARACTERS -> { if (inTitle) titles.add(reader.getText().trim()); } case XMLStreamConstants.END_ELEMENT -> { inTitle = false; } } } } finally { reader.close(); } return titles; } } Always close XMLStreamReader in a finally block or use try-with-resources (it implements AutoCloseable in Java 7+). Failing to close it leaks the underlying stream.
ConstantValueMeaning
START_DOCUMENT7Start of document
END_DOCUMENT8End of document
START_ELEMENT1Opening tag
END_ELEMENT2Closing tag
CHARACTERS4Text content (may be whitespace)
CDATA12CDATA section
COMMENT5XML comment
PROCESSING_INSTRUCTION3Processing instruction
SPACE6Ignorable whitespace
ATTRIBUTE10Standalone attribute (rare)
import javax.xml.stream.*; import javax.xml.stream.events.*; import java.io.*; public class StaxIteratorExample { public static void parse(InputStream xml) throws Exception { XMLInputFactory factory = XMLInputFactory.newInstance(); factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); XMLEventReader reader = factory.createXMLEventReader(xml); try { while (reader.hasNext()) { XMLEvent event = reader.nextEvent(); if (event.isStartElement()) { StartElement start = event.asStartElement(); String name = start.getName().getLocalPart(); if ("book".equals(name)) { Attribute idAttr = start.getAttributeByName( new javax.xml.namespace.QName("id")); System.out.println("Book id: " + (idAttr != null ? idAttr.getValue() : "?")); } if ("title".equals(name)) { // peek at next event (should be Characters) XMLEvent next = reader.nextEvent(); if (next.isCharacters()) { System.out.println("Title: " + next.asCharacters().getData().trim()); } } } if (event.isEndElement()) { String name = event.asEndElement().getName().getLocalPart(); if ("library".equals(name)) break; // early exit cleanly } } } finally { reader.close(); } } } import javax.xml.stream.*; import java.io.*; public class StaxWriteExample { public static String writeLibrary() throws XMLStreamException { StringWriter sw = new StringWriter(); XMLOutputFactory factory = XMLOutputFactory.newInstance(); XMLStreamWriter writer = factory.createXMLStreamWriter(sw); writer.writeStartDocument("UTF-8", "1.0"); writer.writeCharacters("\n"); writer.writeStartElement("library"); writer.writeCharacters("\n "); // First book writer.writeStartElement("book"); writer.writeAttribute("id", "1"); writer.writeAttribute("genre", "technical"); writer.writeStartElement("title"); writer.writeCharacters("Effective Java"); writer.writeEndElement(); // title writer.writeStartElement("author"); writer.writeCharacters("Joshua Bloch"); writer.writeEndElement(); // author writer.writeEndElement(); // book writer.writeCharacters("\n"); writer.writeEndElement(); // library writer.writeEndDocument(); writer.flush(); writer.close(); return sw.toString(); } } XMLStreamWriter does not automatically indent output. For pretty-printed XML, set the javax.xml.stream.isRepairingNamespaces property and manually write whitespace characters, or use a DOM Transformer with OutputKeys.INDENT.

The iterator API supports EventFilter to skip unwanted events before your code sees them.

import javax.xml.stream.*; import javax.xml.stream.events.XMLEvent; import javax.xml.stream.util.EventReaderDelegate; XMLInputFactory factory = XMLInputFactory.newInstance(); XMLEventReader raw = factory.createXMLEventReader(inputStream); // Filter: keep only START_ELEMENT and END_ELEMENT events XMLEventReader filtered = factory.createFilteredReader(raw, (EventFilter) event -> event.isStartElement() || event.isEndElement()); while (filtered.hasNext()) { XMLEvent event = filtered.nextEvent(); // only START_ELEMENT and END_ELEMENT events reach here if (event.isStartElement()) { System.out.println("Start: " + event.asStartElement().getName().getLocalPart()); } } filtered.close();