Simple API for XML

aus Wikipedia, der freien Enzyklopädie

Die Simple API for XML (SAX) ist ein De-facto-Standard, der ein Application Programming Interface (API) zum Parsen von XML-Daten beschreibt. Die aktuelle Hauptversion SAX 2.0 wurde 2000 von David Megginson veröffentlicht und ist Public Domain. Ein SAX-Parser liest XML-Daten als sequentiellen Datenstrom und ruft für im Standard definierte Ereignisse vorgegebene Rückruffunktionen (callback function) auf. Eine Anwendung, die SAX nutzt, kann eigene Unterprogramme als Rückruffunktionen registrieren und auf diese Weise die XML-Daten auswerten.

Arbeitsweise von SAX

SAX wurde ursprünglich in Java entwickelt und besteht aus einer Anzahl von Java-Interfaces, heute finden sich jedoch Implementierungen für nahezu alle gängigen Programmiersprachen. SAX unterliegt keinem formalen Komitee oder Konsortium, was für eine XML-Spezifikation eher untypisch ist, dennoch ist SAX ein De-facto-Standard. Es spezifiziert eine Menge von Methoden für den Zugriff auf XML-Dokumente mittels eines SAX-Parsers. SAX arbeitet, anders als DOM, ereignisorientiert. Das Verarbeitungsprinzip entspricht dem Konzept einer Pipeline. SAX definiert eine Menge von Ereignissen, die beim sequentiellen Lesen eines XML-Dokuments vorkommen können. Diese Ereignisse sind zustandslos, sie referenzieren nicht auf andere, vorhergegangene Ereignisse und stehen auch sonst in keinem Verhältnis zu anderen Ereignissen. Beim Erkennen einer syntaktischen Struktur startet der SAX-Parser eine Behandlungsroutine, welche gegebenenfalls eine individuelle Behandlungsroutine des Ereignisses ausführt.

Hierdurch kann mit dem Einlesen der ersten Zeichen bereits mit der Auswertung des Dokuments begonnen werden. Dies verkürzt insbesondere in interaktiven Systemen die subjektiv gefühlte Zugriffszeit. Gleichzeitig minimiert der SAX-Parser den Speicherbedarf, da neben dem jeweils eingelesenen Element nur solche Daten im Speicher stehen, die mittels einer Behandlungsroutine explizit ausgewählt wurden.

SAX-Ereignisse werden parallel zum Einlesen des Dokuments in den Parser ausgeworfen. In der Praxis bedeutet dies, dass es SAX-Ereignisse auf nicht wohlgeformte XML-Dokumente geben kann, bevor das Dokument als ungültig erkannt wird. Daher spielt die Fehlerbehandlung bei SAX-Parsern eine wichtige Rolle, entsprechende Klassen stehen in Java zur Verfügung. Das Validieren eines XML-Dokuments vor dem Parsen mit SAX widerspricht der Natur von SAX, da hierfür zunächst das gesamte Dokument in den Speicher geladen werden müsste. Dennoch findet sich eine Vielzahl validierender SAX-Parser.

Ereignisse in SAX

Gegeben sei folgendes Dokument:

<?xml version="1.0"?>
<seminararbeit>
 <titel>DOM, SAX und SOAP</titel>
 <inhalt>
  <kapitel value="1">Einleitung</kapitel>
  <kapitel value="2">Hauptteil</kapitel>
  <kapitel value="3">Fazit</kapitel>
 </inhalt>
</seminararbeit>

Wird das gezeigte XML-Dokument mit Hilfe eines SAX-Parsers gelesen, wirft dieser der Reihe nach die folgenden Ereignisse aus[1][2]

SAX-Ereignis Erläuterung
startDocument()
Parser ist auf Anfang des XML-Dokuments gestoßen
startElement("seminararbeit",[])
ein Element mit dem Namen "seminararbeit" wurde gefunden; der 2. Parameter (die eckigen Klammern "[]") ist eine Liste aller zum Element gehörenden Attribute; da dieses Element allerdings keine Attribute hat, ist diese Liste in diesem Fall leer.
characters("\n ")
ein SAX-Parser gibt auch sämtliche Whitespaces aus, die er zwischen zwei Element-Tags findet;[3] in diesem Fall ist das der Zeilenumbruch (newLine, "\n") gefolgt von einem Leerzeichen, welches im XML zur besseren Lesbarkeit für die Zeileneinrückung verwendet wurde.
startElement("titel",[])
characters("DOM, SAX und SOAP")
der Inhalt des Elements "titel"
endElement("titel")
kennzeichnet, dass das Ende des zuvor gefundenen Elements erreicht wurde
characters("\n ")
startElement("inhalt",[])
characters("\n  ")
da die Einrückung im XML nun 2 Leerzeichen beträgt, gibt auch das Ereignis 2 Leerzeichen aus
startElement("kapitel", ["value="1""])
der 2. Parameter enthält eine Liste sämtlicher Attribute; in diesem Fall enthält die Liste nur ein einziges Listenelement, nämlich "value=1".
characters("Einleitung")
endElement("kapitel")
characters("\n  ")
startElement("kapitel", ["value="2""])
characters("Hauptteil")
endElement("kapitel")
characters("\n  ")
startElement("kapitel", ["value="3""])
characters("Fazit")
endElement("kapitel")
characters("\n ")
endElement("inhalt")
characters("\n")
da diese Zeile im XML nicht mehr eingerückt ist, wird nur noch "\n" (ohne folgende Leerzeichen) ausgegeben
endElement("seminararbeit")
endDocument()
Parser hat Ende des XML-Dokumentes erreicht

Bei jedem Ereignis unterbricht der Parser seine Arbeit und wartet darauf, dass er vom Dokument-Handler die Arbeitserlaubnis zurückbekommt. Dieser kann in der Zwischenzeit zur Auswertung des Ereignisses eine Behandlungsroutine starten. Dabei müssen jedoch nur für solche Ereignisse Behandlungsroutinen geschrieben werden, die für die weitere Verarbeitung auch von Interesse sind – ansonsten wird die Kontrolle sofort wieder an den Parser zurückgegeben.

Arbeiten mit SAX

Beispiel in Java

Im folgenden Beispiel in Java soll im Rahmen einer Dokumentenanalyse der Titel und die Anzahl der Kapitel ausgelesen und am Ende ausgegeben werden. Dafür müssen zunächst entsprechende SAX-Klassen importiert werden und der SAX-Parser initialisiert werden. Zusätzlich muss ein Dokument-Handler gestartet werden, der über die Ereignisse vom Parser informiert wird. Dieser Dokument-Handler beinhaltet für das Beispiel folgende Methoden für die Ereignisse „characters“, „startElement“ und „endDocument“:

public int count = 0;
public boolean titel = false;
public String seminararbeit = "";

public void characters(char[] ch, int start, int length) throws SAXException {
 if (titel == true && seminararbeit.equals(""))  {
  seminararbeit = new String(ch, start, length);
  titel = false;
 }
}

public void startElement(String name, AttributeList atts) throws SAXException {
 if (name.equals("kapitel")) ++count;
 if (name.equals("titel")) titel = true;
}

public void endDocument() throws SAXException {
 System.out.println(seminararbeit + " enthält " + count + " Kapitel");
}

Beispiel in Lua

In LuaExpat[4] (Lua mit einem SAX-Parser) werden für das Parsen von XML-Dateien zunächst sogenannte „Callbacks“ vorbereitet, mit denen der Parser seine Daten an das ihn aufrufende Anwendungsprogramm übergeben kann. Im Beispiel sind das einfache Aufrufe von Ausgabefunktionen. Das folgende Programm gibt eine XML-Datei als einfachen Text aus.

require "lxp"
xml_file="irgendeineXMLdatei.xml"

do
  local count = 0
  callbacks = {
    StartElement = function (parser, name, attributes)
      -- StartTag ausgeben--
      io.write("+ ", string.rep(" ", count*2), name, "\n")
      count = count + 1
      -- Attribute ausgeben --
      local attributename
      for _,attributename in ipairs(attributes) do
        io.write("  ", string.rep(" ", count*2),attributename,'="',attributes[attributename],'"\n')
      end
    end,
    EndElement = function (parser, name)
      -- Endtag ausgeben --
      count = count - 1
      io.write("- ", string.rep(" ", count*2), name, "\n")
    end,
    CharacterData = function (parser, text)
      -- Text ausgeben --
      io.write("----------\n",text, "\n----------\n")
    end
  }
end

p = lxp.new(callbacks)          -- Generiere eine Instanz des Parsers
file = assert(io.open(xml_file .. "","r"))
p:parse(file:read("*all"))      -- Parsen der gesamten Datei
                                -- (Auch zeilenweises Einlesen wäre möglich)
file:close();collectgarbage()

p:parse()         -- Beendet das Dokument
p:close()         -- Schließt den Parser

Siehe auch

Literatur

  • David Brownell: SAX2. O’Reilly, ISBN 0-596-00237-8
  • Helmut Erlenkötter: XML Extensible Markup Language von Anfang an. Rowohlt-Taschenbuch-Verlag, Reinbek bei Hamburg 2003, ISBN 3-499-61209-7, S. 211–229.
  • W. Scott Means, Michael A. Bodie: The Book of SAX. No Starch Press, ISBN 1-886411-77-8

Weblinks

Einzelnachweise