XML-Dokumente mit SAX parsen

Wenn Sie ein Abonnement des Magazins 'Access im Unternehmen' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.

XML-Dokumente mit SAX parsen

Wir haben uns bereits in vielen Beiträgen mit dem Parsen von XML-Dokumenten befasst. Dabei haben wir immer den DOM-Parser verwendet, um die im XML-Dokument enthaltenen Daten zu lesen. In diesem Beitrag schauen wir uns eine Alternative namens SAX an. Während DOM das komplette XML-Dokument in den Speicher liest und darauf zugreift, liest SAX das Dokument zeilenweise ein. Im Folgenden erfahren Sie, welche Vor- und Nachteile die beiden Methoden haben und wie Sie mit SAX arbeiten können.

Der DOM-Parser liest ein vollständiges XML-Dokument in den Speicher ein und kann dafür auf alle enthaltenen Elemente zugreifen. Sie können die Elemente damit nacheinander durchlaufen oder mithilfe von XPATH-Ausdrücken und Methoden wie SelectSingleNode oder SelectNodes nach bestimmten Elementen im Dokumentbaum suchen.

Sie können damit im Dokumentbaum vor- und zurückspringen oder die enthaltenen Elemente hierarchisch durchlaufen.

DOM: Vor- und Nachteile

Der Nachteil liegt auf der Hand: Da der komplette Baum im Speicher liegt und mitunter verschachtelt ist, kann der Zugriff auf die Inhalte recht schnell zu Lasten der Performance gehen.

Ein weiterer Nachteil ist, dass sehr große XML-Dateien möglicherweise nicht in den Speicher passen und somit nicht geladen werden können. Dafür können Sie mit DOM aber nicht nur gezielt auf einzelne Elemente zugreifen, sondern den Dokumentbaum und die Inhalte auch bearbeiten.

SAX: Schnell, aber unflexibel

Anders sieht es bei SAX aus. Der SAX-Parser liest das Dokument Zeile für Zeile ein und bietet die Möglichkeit, auf die jeweilige Zeile zuzugreifen. Dabei ist der SAX-Parser rasend schnell! Allerdings liest er auch nur in einer Richtung, ein Hin- und Herspringen oder gar das gezielte Einlesen eines einzelnen Elements ohne Durchlaufen des XML-Dokuments bis zu diesem Punkt ist nicht möglich.

Außerdem können Sie mit dem SAX-Parser keine Änderungen am XML-Dokument vornehmen.

Vorbereitungen

Um den SAX-Parser nutzen zu können, benötigen Sie einen Verweis auf die Objektbibliothek Microsoft XML v6.0 (s. Bild 1).

Setzen eines Verweises auf die Bibliothek Microsoft XML, v6.0

Bild 1: Setzen eines Verweises auf die Bibliothek Microsoft XML, v6.0

Funktionsweise des SAX-Parsers

Wie aber greift der SAX-Parser nun auf das XML-Dokument zu? Öffnet er es wie ein Textdokument und liest dann etwa in einer Schleife die einzelnen Zeilen in eine Variable ein, auf deren Inhalt wir dann per VBA zugreifen können?

Mitnichten: Der SAX-Parser basiert auf Ereignissen. Das heißt, dass es verschiedene Ereignisse gibt:

  • documentLocator(ByVal RHS As MSXML2.IVBSAXLocator): Liefert Informationen etwa über den Speicherort des Dokuments.
  • startDocument(): Wird zu Beginn des Einlesevorgangs ausgelöst.
  • startPrefixMapping(strPrefix As String, strURI As String): Wird beim Einlesen der Namespace-Informationen ausgelöst und liefert mit strPrefix das Kürzel für den NameSpace (zum Beispiel xsi oder xsd) und mit strURI die jeweilige URI.
  • startElement(strNamespaceURI As String, strLocalName As String, strQName As String, ByVal oAttributes As MSXML2.IVBSAXAttributes): Wird für den Start eines jeden Elements ausgelöst (also etwa für ) und liefert mit strNameSpaceURI den Namespace, mit strLocalName den Namen des Elements und mit oAttributes ein Element, mit dem sich die Attribute des Elements auslesen lassen.
  • characters(strChars As String): Wird beim Einlesen eines Teils des Inhalts ausgelöst und liefert mit strChars den Inhalt. Dabei werden immer alle Zeichen geliefert, also auch die Zeilenumbrüche zwischen zwei Elementen, die Einrückungen und natürlich auch die tatsächlichen Inhalte der Elemente.
  • endElement(strName­spaceURI As String, strLocalName As String, strQName As String): endElement wird ausgelöst, wenn das Ende des Elements erreicht wird, also etwa . Die Parameter liefern die bereits weiter oben beschriebenen Werte.
  • endPrefix­Map­ping(str­Prefix As String): Wird ausgelöst, wenn das schließende Element zu dem Element erreicht wird, das eine Namespace-Angabe enthielt.
  • endDocument(): Wird nach der Abarbeitung des letzten Elements ausgelöst.

Die übrigen Ereignisse benötigen wir für die Beispiele dieses Beitrags nicht.

Ereignisse implementieren

Wie implementieren wir diese Ereignisse nun? Als Erstes erstellen Sie ein neues Klassenmodul namens clsSAX. Normalerweise würde man diesem nun eine entsprechende Objektvariable hinzufügen, die mit dem Schlüsselwort WithEvents deklariert wird und so die enthaltenen Ereignisprozeduren verfügbar macht.

In diesem Fall ist dies anders: Wir deklarieren keine Objektvariable, sondern legen mit der Implements-Anweisung fest, dass die Klasse alle Ereignisprozeduren eines speziellen Interfaces implementiert – in diesem Falle für das Interface MSXML2.IVBSAXContentHandler (s. Bild 2).

Implementieren der Klasse IVBSAXContentHandler

Bild 2: Implementieren der Klasse IVBSAXContentHandler

Dessen Ereignisse können Sie dann jedoch genau wie bei mit WithEvents deklarierten Objekten mit den beiden Kombinationsfeldern im oberen Bereich des Codefensters festlegen. Als Erstes fügen wir so das Ereignis startDocument hinzu (s. Bild 3).

Implementieren eines Ereignisses der Klasse IVBSAXContentHandler

Bild 3: Implementieren eines Ereignisses der Klasse IVBSAXContentHandler

Im Gegensatz zu mit Objekten, die Ereignisse auslösen, müssen Sie jedoch bei der Implementierung eines Interfaces alle Elemente anlegen. Anderenfalls löst das Debuggen des VBA-Projekts den Fehler aus Bild 4 aus. Wenn Sie alle Ereignisprozeduren hinzugefügt haben, ist der erste Teil erledigt.

Die Implementierung der Klasse IVBSAXContentHandler ist noch nicht vollständig.

Bild 4: Die Implementierung der Klasse IVBSAXContentHandler ist noch nicht vollständig.

Nun liegt uns allerdings zunächst einmal eine Klasse vor, die allein noch nichts ausrichtet. Wir müssen zunächst ein Objekt auf Basis dieser Klasse deklarieren und instanzieren sowie der Klasse mitteilen, dass sie in Aktion treten soll.

Dies erledigen wir gleich einmal in einem Formular, das auch die Steuerelemente zum Auswählen der zu untersuchenden XML-Datei sowie eine Schaltfläche zum Starten des Vorgangs enthalten soll. Dieses Formular sieht im ersten Entwurf wie in Bild 5 aus. Die Schaltfläche Einlesen soll das angegebene XML-Dokument mithilfe der Klasse clsSAX einlesen.

Das Formular frmSAX

Bild 5: Das Formular frmSAX

Dazu legen Sie die Ereignisprozedur aus Listing 1 an. Die Prozedur deklariert gleich zwei Objektvariablen: objSax soll ein Objekt auf Basis der soeben erstellten Klasse clsSAX aufnehmen. objReader nimmt ein Objekt des Typs SAXXMLReader60 auf, das Teil der Objektbibliothek Microsoft XML, v6.0 ist.

Private Sub cmdEinlesen_Click()
     Dim objReader As SAXXMLReader60
     Dim objSax As clsSAX
     Set objReader = New SAXXMLReader60
     Set objSax = New clsSAX
     Set objReader.contentHandler = objSax

Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.

Bitte geben Sie die Zeichenfolge in das nachfolgende Textfeld ein

Die mit einem * markierten Felder sind Pflichtfelder.

Ich habe die Datenschutzbestimmungen zur Kenntnis genommen.