XML Tutorial · XML in Code · Lesson 19 of 28
XML in Java
Java's built-in XML APIs: DOM, SAX, StAX and the Transformer, plus secure parser settings and JAXB-style data binding.
The JAXP family
| API | Style | Use for |
|---|---|---|
DOM (DocumentBuilder) |
Whole tree in memory | Small and medium documents you edit or query |
SAX (SAXParser) |
Push: callbacks per event | Large documents, read once |
StAX (XMLStreamReader / Writer) |
Pull: you ask for the next event | Large documents, simpler than SAX |
XPath (javax.xml.xpath) |
Queries over a DOM | Selecting nodes |
Transformer (javax.xml.transform) |
XSLT 1.0, serialising | Transforming and writing XML |
Validation (javax.xml.validation) |
XSD 1.0 | Checking documents |
Jakarta XML Binding (JAXB, formerly built into Java 8) and Jackson XML map XML to Java objects with annotations; both are separate libraries today.
Java examples aren't runnable in the browser; the output shown is from a real JDK 21 run.
SAX: events as the parser reads
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
import java.io.ByteArrayInputStream;
public class Main {
public static void main(String[] args) throws Exception {
String xml = """
<shop>
<product sku="TEA-01" category="drinks"><name>Green tea</name><price>3.50</price><stock>40</stock></product>
<product sku="COF-02" category="drinks"><name>Coffee beans</name><price>9.90</price><stock>0</stock></product>
<product sku="MUG-07" category="kitchen"><name>Camel mug</name><price>12.00</price><stock>15</stock></product>
<product sku="PAN-03" category="kitchen"><name>Frying pan</name><price>29.00</price><stock>4</stock></product>
</shop>""";
var handler = new DefaultHandler() {
String current = "";
double total = 0;
StringBuilder text = new StringBuilder();
@Override public void startElement(String uri, String local, String qName, Attributes atts) {
if (qName.equals("product")) current = atts.getValue("sku");
text.setLength(0);
}
@Override public void characters(char[] ch, int start, int length) { text.append(ch, start, length); }
@Override public void endElement(String uri, String local, String qName) {
if (qName.equals("price")) {
total += Double.parseDouble(text.toString());
System.out.println(current + " costs " + text);
}
}
@Override public void endDocument() { System.out.println("total: " + total); }
};
SAXParserFactory.newInstance().newSAXParser().parse(new ByteArrayInputStream(xml.getBytes("UTF-8")), handler);
}
}
Output
TEA-01 costs 3.50 COF-02 costs 9.90 MUG-07 costs 12.00 PAN-03 costs 29.00 total: 54.4
Run this on your computer — see “Get Started” for setup.
StAX: pull parsing and writing
import javax.xml.stream.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
String xml = """
<shop>
<product sku="TEA-01" category="drinks"><name>Green tea</name><price>3.50</price><stock>40</stock></product>
<product sku="COF-02" category="drinks"><name>Coffee beans</name><price>9.90</price><stock>0</stock></product>
<product sku="MUG-07" category="kitchen"><name>Camel mug</name><price>12.00</price><stock>15</stock></product>
<product sku="PAN-03" category="kitchen"><name>Frying pan</name><price>29.00</price><stock>4</stock></product>
</shop>""";
XMLStreamReader r = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(xml));
StringWriter out = new StringWriter();
XMLStreamWriter w = XMLOutputFactory.newInstance().createXMLStreamWriter(out);
w.writeStartElement("restock");
String sku = null;
while (r.hasNext()) {
if (r.next() == XMLStreamConstants.START_ELEMENT) {
if (r.getLocalName().equals("product")) sku = r.getAttributeValue(null, "sku");
if (r.getLocalName().equals("stock") && Integer.parseInt(r.getElementText()) < 5) {
w.writeEmptyElement("item");
w.writeAttribute("sku", sku);
}
}
}
w.writeEndElement();
w.close();
System.out.println(out);
}
}
Output
<restock><item sku="COF-02"/><item sku="PAN-03"/></restock>
Run this on your computer — see “Get Started” for setup.
Java's DocumentBuilderFactory resolves external entities by default. Always configure it securely for untrusted
input; see XML security.
Test yourself
Which Java XML API lets your code ask for the next event, rather than receiving callbacks?
StAXSAXDOMJAXB
Show answer
Answer: StAX
StAX is a pull parser; SAX pushes events to a handler.