StAX ist eine Programmierschnittstelle, die das Lesen und Schreiben von XML-Dokumenten in Java ermöglicht. Die reine Java-API basiert auf Schnittstellen, die von unterschiedlichen Parsern implementiert werden können.
StAX (Streaming API for XML) wurde mit Java 6.0 eingeführt. Die Schnittstelle steht in dem Ruf, SAX[1] (Simple API for XML) und DOM[2] (Document Object Model) überlegen zu sein. ZDNet wirft nachfolgend einen Blick auf die API, erklärt die Funktionsweise und liefert einige Code-Beispiele.
Eine kurze Einführung in StAX
XML-APIs sind traditionell entweder baum- oder ereignisbasiert. Bei baumbasierten APIs wird das gesamte Dokument als Baumstruktur in den Speicher gelesen. Damit hat die bearbeitende Anwendung wahlfreien Zugriff darauf. Bei ereignisbasierten XML-APIs reagiert die Anwendung auf empfangene Ereignisse, sobald sie auf bestimmte Elemente innerhalb des Quelldokuments stößt.
Baumbasierte APIs, etwa DOM, ermöglichen den wahlfreien Zugriff auf das Dokument. Ereignisbasierte APIs, beispielsweise SAX, benötigen jedoch weniger Speicherplatz und arbeiten normalerweise wesentlich schneller.
Diese beiden Zugriffsmethoden stellen also zwei entgegengesetzte Ansätze dar. Eine baumbasierte API gewährt unbegrenzten und wahlfreien Zugriff sowie Manipulationsmöglichkeiten. Die ereignisbasierte API durchläuft das Quelldokument dagegen nur ein einziges Mal.
StAX wurde als eine Art Zwischenstufe zwischen diesen beiden Extrempositionen entwickelt. Bei StAX besteht der programmiertechnische Einstiegspunkt in einem Cursor, der einen Punkt innerhalb des Dokuments repräsentiert. Die Anwendung bewegt diesen Cursor vorwärts, das heißt sie "zieht" (pull) die Informationen nach Bedarf vom Parser ab. Dies unterscheidet sich von einer ereignisbasierten API, die die Daten eher zur Anwendung "schiebt" (push). Das setzt voraus, dass sich die Anwendung den Status zwischen den Ereignissen gegebenenfalls merkt. So weiß sie jederzeit, an welcher Stelle innerhalb des Dokuments sie sich gerade befindet.
StAX verwendet ein Pull-Konzept. Folglich fragt der Entwickler Ereignisse ab, anstatt Ereignisinformationen vom XML-Parser automatisch an den Client schicken zu lassen (Push-Ansatz). Das führt letztlich zu einem natürlicheren, lesbareren Programmcode, ohne dass dies zu Lasten der Performance geht. StAX hat seine Wurzeln in einer Reihe inkompatibler Pull-APIs für XML. XMLPULL ist wohl die bekannteste davon.
So funktioniert die StAX-API
Die Kern-API von StAX besteht aus zwei Komponenten: der Event-Iterator-API und der Cursor-API. Anwendungen können diese APIs zum Lesen, Parsen und Schreiben von XML-Dokumenten verwenden.
Die Event-Iterator-API
Die Event-Iterator-API ist SAX sehr ähnlich. Sie hat zwei wichtige Schnittstellen: den XMLEventReader zum Parsen von XML und den XMLEventWriter zum Erzeugen von XML-Code.
Als Beispiel soll folgende einfache XML-Datei dienen:
Der folgende Code liest die XML-Datei und schickt den Inhalt der Beispieldatei an die Standardausgabe:
Um denselben Inhalt in die Datei rootfile2.xml zu schreiben, bietet sich diese Möglichkeit an:
Der Konstruktionsprozess für XML hat Ähnlichkeit mit dem DOM-Konzept, unterscheidet sich aber doch ein wenig davon. Der Code dürfte selbsterklärend sein.
Die XMLStreamReader-Schnittstelle repräsentiert einen Cursor, der vom Anfang bis zum Ende eines XML-Dokuments bewegt wird. Zu jedem Zeitpunkt zeigt dieser Cursor auf eines der folgenden Elemente: einen Textknoten, einen Start-Tag, einen Kommentar, den Anfang des Dokuments und so weiter. Der Cursor bewegt sich immer vorwärts, in der Regel jeweils nur um ein Element.
Der Aufruf von Methoden wie getName() oder getText() auf dem XMLStreamReader liefert Informationen über das Element, an dem der Cursor derzeit positioniert ist.
Und so wird üblicherweise ein Parser geladen, der von der installierten StAX-Implementierung abhängt:
Der XMLStreamReader lässt sich aus jeder anderen Nachfolgerklasse von java.io.Reader erstellen. Die next()-Methode bewegt den Cursor zum nächsten Element. Wenn der Cursor am aktuellen Element positioniert ist, stehen unterschiedliche Getter-Methoden zur Verfügung, um Daten vom aktuellen Element abzurufen. Dies sind die wichtigsten Getter-Methoden:
Der letzte Codeschnipsel liest ein XHTML-Dokument und druckt den Inhalt aller Überschriften-Elemente h1 und h2 aus.
Das Schreiben von XML erfolgt über die XMLStreamWriter-Schnittstelle. Dabei werden Methoden zum Festlegen von Elementen, Attributen, Kommentaren, Text und allen anderen Teilen eines XML-Dokuments bereitgestellt. Ein XMLStreamWriter wird wie folgt von einer XMLOutputFactory erstellt:
OutputStream out = new FileOutputStream("data.xml");
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter writer = factory.createXMLStreamWriter(out);
Anschließend kommen unterschiedliche writeXXX()- Methoden zum Einsatz:
writer.writeStartDocument("ISO-8859-1", "1.0");
writer.writeStartElement("greeting"); writer.writeAttribute("id", "g1");
writer.writeCharacters("Hello StAX"); writer.writeEndDocument();
Ist das Dokument fertiggestellt, sollten der Speicher bereinigt und der Writer geschlossen werden. Doch das beendet nicht gleichzeitig den zugrundeliegenden Output-Stream. Daher gilt es, diesen ebenfalls zu schließen:
writer.flush(); writer.close(); out.close();
XMLStreamWriter hilft, für die Vollständigkeit des XML-Codes zu sorgen. So schließt beispielsweise endDocument alle ungeschlossenen Start-Tags. writeCharacters führt sämtliche erforderlichen Maskierungen von reservierten Zeichen wie "&" oder "<" durch. Allerdings fällt die Überprüfung nur minimal aus.
Welche StAX-Implementierungen gibt es?
Eine Reihe von StAX-Implementierungen ist verfügbar. Am wichtigsten sind die StAX-Implementierung von Sun[3], Woodstox[4] (eine Open-Source-Implementierung von StAX) sowie die StAX-Referenzimplementierung von Codehaus[5].
Darüber hinaus bietet das StAX-Utils-Project[6] eine Reihe von Utility-Klassen, die eine Integration von StAX in vorhandene Anwendungen zur XML-Verarbeitung erleichtern. StAX-Utils enthält zum Beispiel Klassen zum Einrücken und Formatieren des Codes in XML-Dateien.
Weitere Quellen:
- JSR 173: eine Streaming-API für XML[7]
- Die JAXP-Referenzimplementierung[8] enthält ebenfalls StAX.
- JAXP JavaDoc[9]
URLs in diesem Artikel:
[1] = http://www.zdnet.de/builder/program/0,39023551,20000885,00.htm
[2] = http://www.zdnet.de/builder/program/0,39023551,39152555,00.htm
[3] = https://sjsxp.dev.java.net/
[4] = http://woodstox.codehaus.org/
[5] = http://stax.codehaus.org/
[6] = https://stax-utils.dev.java.net/
[7] = http://jcp.org/en/jsr/detail?id=173
[8] = https://jaxp.dev.java.net/
[9] = https://jaxp-sources.dev.java.net/nonav/docs/api/