Abstract

Für diverse Programmiersprachen existieren mittlerweile gängige Schnittstellen, um auf XML-Dokumente zuzugreifen und diese weiterzuverarbeiten. Die Simple API for XML (SAX) ist eine sehr einfach (=leichtgewichtig) gehaltene API für die ereignisbasierte Verarbeitung von XML-Dokumenten. Die Charakterisierung als leichtgewichtiger Ansatz bezieht sich sowohl auf den Implementierungsaufwand der API selbst, als auch ihren Integrationsaufwand in eigene Applikationen.

XML-APIs - baumorientiert vs. ereignisbasiert

Für die Verarbeitung von XML-Dokmenten sind im Wesentlichen zwei Ansätze verfügbar.

Was ist ein Parser? Was sind seine Aufgaben?

Ein Parser (engl. to parse „analysieren“ bzw. von lateinisch pars „Teil“; im Deutschen gelegentlich auch Zerteiler) ist ein Computerprogramm, das in der Computertechnik für die Zerlegung und Umwandlung einer beliebigen Eingabe in ein für die Weiterverarbeitung brauchbares Format zuständig ist. Häufig werden Parser eingesetzt, um im Anschluss an den Analysevorgang die Semantik der Eingabe zu erschließen und daraufhin Aktionen durchzuführen.

Quelle: Wikipedia

SAX - Einführendes

Bestandteile von SAX Implementierungen

SAX-Implementierungen weisen üblicherweise drei erkennbare Blöcke auf.

Die SAX2 Schnittstellen

Ausflug in den Compilerbau: deterministisches Inhaltsmodell

Das SAX Ausführungsmodell

SAX - Leichtgewichtiger Ansatz

Push Model

SAX - Ein erstes Beispiel

import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.FileReader;
import org.xml.sax.InputSource;

public class SAXExample1 extends DefaultHandler {
 
    public void startDocument() {
        System.out.println("document started");
    } //startDocument()

    public void endDocument() {
        System.out.println("document ended");
    } //endDocument()

    public static void main(String args[]) throws Exception {
     XMLReader xr = XMLReaderFactory.createXMLReader();
     SAXExample1 handler = new SAXExample1();
     xr.setContentHandler(handler);
     xr.setErrorHandler(handler);

     FileReader r = new FileReader(args[0]);
     xr.parse(new InputSource(r));

    } //main()

    public SAXExample1 ()
    {
     super();
    }
    
}//class SAXExample1

SAX - erste Übung

SAX - erstes Beispiel - Analyse (1/2)

Was ist während der Ausführung des Beispiels passiert?
Eine Analyse.

SAX - erstes Beispiel - Analyse (2/2)

SAX - Erweiterung des ersten Beispiels

Die SAX2-Schnittstellen

Die grundlegende Schnittstelle der SAX2-API wird mit ContentHandler bezeichnet, sie versammelt Operationen zur Abbildung des logischen Inhaltes eines XML-Dokumentes. Die in unseren Beispielen verwendete Basisklasse DefaultHandler implementiert u.a. diese Schnittstelle und stellt sie so der Beispielapplikation zur Verfügung.
Die Übersicht in untenstehender Tabelle stellt die wichtigsten Operationen der Schnittstelle mit ihrer Signatur und Funktionalität zusammen.

Operation Funktionalität
startDocument() Aufruf zu Beginn eines Dokuments. Naturgemäß wird diese Methode nur einmal ausgeführt.
endDocument() Aufruf am Ende des Einlesevorgangs eines Dokuments. Auch diese Methode wird vom SAX Parser nur einmal aufgerufen.
startElement(String namespaceURI, String localName, String qName, Attributes atts) Die Operation wird am Anfang (öffnender Tag) eines jeden Elements in einem XML-Dokument aufgerufen (auch bei leeren Elementen!). Sie gibt unter den Namen des Elementes als Namen ohne Namensraumpräfix ( localName ) sowie auch den qualifizierten Namen des Elements ( qName ) zurück.
Anmerkung: Namensrauminformationen werden nur erzeugt, wenn der Parser entsprechend konfiguriert wurde.
Das bedeutet z.B., der qualifizierte Name wird nur dann zurückgegeben, wenn der Parser konfiguriert wurde, Namensraum-Präfixe zu verwenden.

Objekte des Type Attributes enthalten die Attribute eines Elements in der Reihenfolge ihrer Definition.
Zu jedem Attribut sind neben dem lokalen und dem qualifizierten Namen die Namensraum URI sowie Typ und Attributwert gemäß XML v1.0 abrufbar.
endElement(String namespaceURI, String localName, String qName) Die Operation wird aufgerufen, wenn das Ende eines jeden Elements in einem XML-Dokument erreicht ist (auch bei leeren Elementen!)
Die Übergabeparameter entsprechen denen des zugehörigen startElement-Aufrufs.
processingInstruction(String target, String data) Liefert die deklarierten Verarbeitungsanweisungen. Diese können vor und nach Eintritt des startDocument -Ereignisses auftreten. Der XML-Prolog wird hierbei nicht als Processing Instruction behandelt, entsprechend wird daher auch kein Ereignis dieses Typs ausgelöst.
startPrefixMapping(String prefix, String uri) Signalisiert den Beginn des Gültigkeitsbereits des Namensraumkürzels prefix . uri enthält die vollständige URI des gebundenen Namensraums. Ist prefix leer, so handelt es sich um die Redefinition des Vorgabenamensraums. Das Ereignis wird vor dem ersten Element des Namensraums (d.h. dem Element, das die Präfixbindung enthält oder den Vorgabenamensraum überschreibt) ausgelöst.
endPrefixMapping(String prefix) Signalisiert das Ende des Gültigkeitsbereichs des Namensraumkürzels prefix . Ist der Übergabeparameter leer, so bezieht sich das Ereignis auf den Vorgabenamensraum. Das Ereignis tritt nach dem endElement -Ereignis des letzten Elements im Namensraum ein.
characters(char[] ch, int start, int length) Aufruf bei der Verarbeitung von Zeichenkettendaten innerhalb eines Elements. ch enthält ab der Position start Zeichenketten-artige Daten der Länge length .
Hinweis: Manche Parser melden Leerzeichen innerhalb von Elementen mit Hilfe der Operation ignorableWhitespace . Validierenden Parsern ist dies sogar vorgeschrieben.
ignorableWhitespace(char[] ch, int start, int length) Diese Operation wird aufgerufen, wenn der Parser ignorierbare Leerzeichen im Inhalt von Elementen liest.
Validierende Parser müssen hierbei diese Operation verwenden, nicht validierende Parser können sie verwenden.

Beispiel 3 - Eine kleine Dokumentstatistik

Beispiel 3 - Analyse

Beispiel 3 - komplettes Listing

Beispiel 4 - Häufigkeitsermittlung einzelner Elementnamen

Beispiel 4 - komplettes Listing

SAX - Probleme des Xerces-Parsers mit der Byte Order Mark (1/3)

SAX - Probleme des Xerces-Parsers mit der Byte Order Mark (2/3)

Die Unicode Byte Order Mark

SAX - Probleme des Xerces-Parsers mit der Byte Order Mark (3/3) - Lösung

Namensraum-konformer SAX-Parser

Beispiel 5 - Elemente zählen mit Namensraumunterstützung

SAX Features

Fehlerbehandlung

Fehlerbehandlung - SAXNotRecognizedException

Fehlerbehandlung - SAXParseException

Fehlerbehandlung - SAXNotSupportedException

Abschließendes Beispiel

Einfache Transformationen

Einbindung von SAX in Applikationsprogramme

Abschlußbemerkungen und Einsatzempfehlungen