Events und Handler

(Auszug aus "Perl & XML" von Erik T. Ray & Jason McIntosh)

Warum sprechen wir von einem Eventstrom ? Die Bezeichnungen Elementstrom oder Strom von Markupobjekten wären doch ebenso plausibel? XML ist hierarchisch aufgebaut: Elemente enthalten andere Elemente. Dadurch verbietet es sich, einzelne Elemente als Token im Strom zu servieren. In einem wohlgeformten Dokument müssen alle anderen Elemente innerhalb des Wurzelelements stehen. Ein das gesamte Dokument enthaltendes Wurzelelement ist aber kein Strom. Damit verbietet es sich also, aus einem Element ein einzelnes Token zu machen – von leeren Elementen einmal abgesehen.

XML-Ströme bestehen also statt dessen aus Events. Ein Event ist ein Signal, daß sich der Status des Dokuments (soweit wir ihn bisher aus dem Strom kennen) geändert hat. Wenn der Parser zum Beispiel das Start-Tag eines Elements gefunden hat, dann signalisiert er, daß dieses Element geöffnet wurde. Der Status des Dokuments hat sich geändert: Die Verschachtelungstiefe der Elemente ist erhöht worden. Ein End-Tag betrifft den Status in ähnlicher Weise, indem das letzte offene Element geschlossen wird. Ein XML-Prozessor kann offene Elemente in einem Stack oder einer ähnlichen Datenstruktur speichern. Neu geöffnete Elemente werden auf den Stack geschoben, geschlossene werden entfernt. Die Tiefe des Stacks entspricht dann der jeweils aktuellen Verschachtelungstiefe.

Obwohl Parser eine Vielzahl von Events unterstützen, gibt es doch gewisse Überschneidungen. Zum Beispiel unterscheidet ein Parser möglicherweise ein Start-Tag und ein leeres Element, ein anderer dagegen signalisiert in beiden Fällen ein Start-Tag (gefolgt vom Signal eines End-Tags). In jedem Fall wird aber die Präsenz des Elements signalisiert. Im folgenden Beispiel sehen Sie, wie ein solcher Eventstrom aussehen kann.

Beispiel: XML-Fragment

<?xml version="1.0" encoding="ISO-8859-1"?>
<rezept>
    <name>Sandwich aus Erdnußbutter und Marmelade</name>
    <!-- Hier bitte ein Bild des Sandwich einfügen. -->
    <zutaten>
        <zutat>Erdnußbutter der Marke WasAuchImmer&trade;</zutat>
        <zutat>Brot</zutat>
        <zutat>Marmelade</zutat>
    </zutaten>
    <anweisungen>
        <vorgang>Streiche die Erdnußbutter auf eine Scheibe Brot.</vorgang>
        <vorgang>Streiche die Marmelade auf eine andere Scheibe Brot.</vorgang>
        <vorgang>Lege die beiden Scheiben aufeinander, so daß sich
            Erdnußbutter und Marmelade berühren.</vorgang>
    </anweisungen>
</rezept>

Wenn wir einen Parser auf dieses XML-Dokument loslassen, dann sollte er in etwa die folgenden Events generieren:

  1. Den Start eines Dokuments (d. h. den Beginn eines Dokuments und nicht eines Fragments)
  2. Ein Start-Tag für das Element <rezept>
  3. Ein Start-Tag für das Element <name>
  4. Ein Stück Text, »Sandwich aus Erdnußbutter und Marmelade«
  5. Das End-Tag des Elements <name>
  6. Einen Kommentar mit dem Text »Hier bitte ein Bild des Sandwich einfügen.«
  7. Ein Start-Tag für das Element <zutaten>
  8. Ein Start-Tag für das Element <zutat>
  9. Den Text »Erdnußbutter der Marke WasAuchImmer«
  10. Eine Referenz auf das Entity »trade«
  11. Das End-Tag des Elements <zutat>

…und so weiter, bis schließlich das letzte Event erscheint, nämlich das Ende des Dokuments.

Irgendwo zwischen der Aufteilung des Stroms in einzelne Token und der Verarbeitung dieser Token ist eine weitere Softwareschicht, die wir als Dispatcher bezeichnen könnten. Der Dispatcher steuert die weitere Verarbeitung abhängig vom Typ des Token. Der Code, der einen bestimmten Tokentyp verarbeitet, heißt Handler. Es kann einen Handler für Start-Tags geben, einen für Zeichendaten usw. Genausogut könnte es ein einzelner Handler sein, der ein komplexes if-Statement enthält, in dem er je nach Tokentyp mal die eine, mal die andere Subroutine aufruft. (Dann ist er selbst ein Dispatcher.) Oder es könnte ein Stück in den Parser eingebaute Software sein, die sich ihrerseits als Dispatcher betätigt und andere Events generiert – so wie es zum Beispiel der Stream-Modus von XML::Parser tut. Im Normalfall wird man aber eher eine Menge von Subroutinen registrieren – eine pro Eventtyp – und dem Parser den Aufruf der richtigen überlassen. Welche Strategie Sie wählen, hängt von Ihnen selbst und ein Stück weit vom eingesetzten Parser ab.

  

  

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema Perl & XML bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © 2003 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "Perl & XML" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O’Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de