XML-Parser

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

Das Lesen und Schreiben von Dateien ist ein wesentlicher Bestandteil einer Programmiersprache. In der Vergangenheit wurde das aber stets auf einer relativ niederen Ebene erledigt: Einzelne Zeichen wurden gelesen, im besten Fall ganze Zeilen, die dann mit regulären Ausdrücken analysiert wurden. Roher Text ist eine unerfreuliche Sache, frei von klaren Regeln, die einzelne Teile abgrenzen. Mehr als Zeilen oder durch Tabulatorzeichen getrennte Spalten können wir nur selten unterscheiden. Aus diesem Grund sind in der Vergangenheit derartig viele Datenspeicherungsformate entstanden, daß die Erbauer des Turms von Babel vor Neid erblassen würden. Dieser Mißstand war einer der wichtigsten Beweggründe für die Entwicklung von XML mit seinen klaren Regeln zur Abgrenzung von Daten, zum Aufbau einer Hierarchie und zur Verbindung der einzelnen Teile in einer vorhersagbaren, unzweideutigen Art und Weise. Ein Programm, das sich auf diese Regeln verläßt, kann jedes wohlgeformte XML-Dokument lesen, als hätte ihm jemand einen Babelfisch (Anmerkung: Die Leser von Per Anhalter durch die Galaxis von Douglas Adams werden sich daran erinnern, daß ein Babelfisch ein lebendes Gerät zur Übersetzung beliebiger Sprachen ist, ungefähr so groß wie eine Olive. Wenn man ihn mit dem Kopf voran ins Ohr steckt, paßt er genau in den Gehörkanal.) ins Ohr gesteckt.

Wo bekommen wir diesen Babelfisch? Der XML-Parser ist ein Programm bzw. eine Bibliothek, das bzw. die XML-Dokumente liest und für uns bereitstellt. Das kann geschehen, indem wir einen Strom von Events bekommen. Auf Wunsch erhalten wir aber auch ein großes, komplexes Datenobjekt, mit dem wir direkten Zugriff auf die einzelnen Bestandteile eines Dokuments haben. Wir können aus einer oder mehreren Dateien lesen, aus einem Zeichen-Stream oder aus einem String. Das XML-Dokument darf mit Entityreferenzen gewürzt sein. Wer es scharf mag, läßt die Entityreferenzen stehen, milder und verträglicher ist es, wenn der XML-Parser die Entities ersetzt, so daß wir sie gar nicht erst zu sehen bekommen. Einige Teile des Dokuments kommen möglicherweise von außerhalb unseres Computersystems, aus irgendeiner weit entfernten Ecke des Internet. Das Dokument kann in ISO-8859-1 verfaßt sein, genausogut aber in einem japanischen Zeichensatz. Der Anwender muß sich nur wenig mit diesen Dingen befassen. Zum Glück, denn diese Anwender sind wir. Alle Einzelheiten übernimmt der Parser, ein abstrakter Tunnel vom physikalischen Speicherungszustand der Daten zu einer kristallklaren Repräsentation, die unsere Unterprogramme zu sehen bekommen.

Ein XML-Parser ist eine Brücke zwischen den Markup-Daten, d. h. den mit eingebetteten XML-Anweisungen versehenen Textdaten, und einem vorgefertigten Format, mit dem unsere Programme umgehen können. Im Falle von Perl bekommen wir letzten Endes Hash- und Arrayreferenzen sowie Skalare zu sehen, also vertraute alte Freunde. XML kann sehr komplex werden, aus vielen verschiedenen Dateien oder Strömen zusammenfließen und unerforschte Regionen (die Entities) enthalten, die wir umgehen müssen. Aber wir können uns beispielsweise darauf verlassen, daß der Parser nur sauberes XML akzeptiert und jede Verletzung der Wohlgeformtheitsregeln zurückweist. Seine Ausgabe muß die Struktur des Dokuments wiedergeben, d. h. die Reihenfolge der einzelnen Teile, Abgrenzung und die Assoziationen von Daten und Namen. Irrelevante Details wie zum Beispiel den Namen der gelesenen Datei oder den darin benutzten Zeichensatz soll uns der Parser dagegen am besten vorenthalten. Das ist eine ganze Menge Arbeit. Fassen wir die Aufgaben des XML-Parsers noch einmal zusammen:

  • Zeichenströme werden gelesen, Markup und Textdaten werden unterschieden
  • Optional werden Entities durch ihre Werte ersetzt
  • Aus möglicherweise verschiedenen Quellen wird ein komplettes, logisches Dokument aufgebaut
  • Syntaxfehler werden entdeckt und protokolliert, eventuell auch grammatikalische Fehler, d. h. Verstöße gegen eine DTD oder ein Schema
  • Daten und strukturelle Informationen werden an das Programm übergeben

In XML werden Daten und Markup vermischt. Die erste Aufgabe des Parsers ist also die Trennung dieser einzelnen Bestandteile aus dem gelesenen Zeichenstrom heraus. Gewisse Sonderzeichen dienen der Unterscheidung von Anweisungen und Daten, insbesondere das Kleiner- und das Größer-Zeichen (< und >) für Elemente, Kommentare und PIs. Aber auch das Ampersand (&) und das Semikolon (;) müssen als Markierung einer Entityreferenz korrekt behandelt werden. Der Parser weiß, wann eine gegebene Anweisung erlaubt ist und wann nicht. Ein Element, das Textdaten oder andere Elemente enthält, muß zum Beispiel nicht nur ein Start-Tag, sondern auch ein End-Tag besitzen. Die Kenntnis dieser Zusammenhänge erlaubt es dem Parser, den Zeichenstrom sehr schnell in die durch den XML-Markup beschriebenen Einzelteile zu zerlegen.

Die nächste Aufgabe ist das Ersetzen von Platzhaltern. Entityreferenzen müssen aufgelöst werden. In einem frühen Stadium des Parsens erstellt der XML-Prozessor eine Liste von definierten Platzhaltern. Die Liste verbindet einen kurzen Bezeichner, den Entitynamen, mit dem Entity. Das Entity ist mit seinem Namen in der DTD deklariert, der Wert kann entweder direkt dort gelesen werden oder durch Lesen eines URL ermittelt werden. Entitywerte können ihrerseits Entityreferenzen enthalten. Darum können verschiedene Iterationen erforderlich sein, bevor alle Entitities aufgelöst sind.

In einigen Fällen ist es nicht wünschenswert, daß Entities aufgelöst werden. Wenn Sie nur einige kleinere Änderungen vornehmen wollen, um das Dokument anschließend zurückzuschreiben, dann kann es sinnvoll sein, die Auflösung von Entities ganz zu unterbinden oder wenigstens durch ein eigenes Stück Quelltext erledigen zu lassen. Zum Beispiel wäre es denkbar, externe Entities (die sich hinter einer URL auf fremden Rechnern verbergen) aufzulösen, weil man diese nicht in der Hand hat, interne dagegen zu lassen, wie sie sind. Die meisten Parser versetzen Sie in die Lage, solche raffinierten Kniffe anzuwenden. Keiner wird hingegen eine Entityreferenz ohne vorherige Deklaration erlauben.

Damit kommen wir zur dritten Aufgabe. Wenn Sie dem Parser die Auflösung externer Entities erlauben, dann wird er alle erforderlichen Dokumente zusammentragen, egal ob sie vom eigenen Rechner oder einem anderen stammen. Durch diesen Vorgang wird aus getrennten Teilen ein einzelnes großes Dokument. Da es für ein Programm normalerweise nicht relevant ist, wo die verarbeiteten Daten physikalisch herkommen, werden beim Einfügen der einzelnen Bestandteile in das Gesamtdokument die Informationen über ihre Herkunft verworfen.

Während der Markup interpretiert wird, kann der Parser einen Syntaxfehler entdecken. Die Konzeption von XML macht die Erkennung solcher Fehler sehr einfach. Von Attributen bis zu leeren Elementen gibt es für alles sehr strenge Regeln. Der Parser kann deswegen sehr einfach sagen, was korrekt ist bzw. was eben nicht. Zum Beispiel enthält das folgende Stück XML einen offensichtlichen Fehler. Das Start-Tag des Elements <Dekret> enthält ein Attribut mit einer ungültigen Wertzuweisung. Der Wert »sofort« ist nicht auf beiden Seiten mit doppelten Anführungszeichen umgeben, sondern nur am Anfang. Auch das End-Tag enthält einen Fehler. Sehen Sie ihn?

<Dekret gueltig="sofort>Alle Motorräder sind rot anzustreichen.</Dekret<

Wenn solche Fehler auftreten, dann bleibt dem Parser kaum eine andere Wahl, als die Arbeit einzustellen. Es macht keinen großen Sinn, das Dokument weiterzuanalysieren. Es ist ein wesentliches Prinzip von XML, Zweideutigkeiten zu beseitigen. Wenn der Parser raten sollte, wie das Dokument aussehen könnte, (Anmerkung: Die meisten HTML-Browser versuchen solche Fehler in HTML-Dokumenten zu erkennen, zu ignorieren oder sogar zu korrigieren. Auf den ersten Blick ist das angenehmer und klingt überzeugend. In der Praxis hat es aber dazu geführt, daß sich die Autoren von HTML-Dokumenten sehr nachlässig verhalten, und es hat zu einer allgemeinen Verschlechterung der Qualität von Webinformationen beigetragen. Seien wir ehrlich: Würden Sie solche Fehler beseitigen, wenn Sie nicht wirklich müßten?) dann würde das den ersten Schritt in Richtung Unsicherheit bedeuten. Das Vertrauen in die Exaktheit des Programms würde schwinden. Die XML-Architekten entschieden sich statt dessen dafür, daß ein XML-Parser an dieser Stelle einfach eine Fehlermeldung auszugeben und die Arbeit einzustellen hat. Wir glauben, daß das eine weise Entscheidung war. Wenn der XML-Parser dagegen ein Dokument klaglos liest, dann nennen wir es wohlgeformt.

Was ist mit »grammatikalischen Fehlern« gemeint? Sie kommen nur bei sogenannten validierenden Parsern vor. Ein Dokument heißt gültig (»Valid«), wenn es die durch eine DTD vorgegebenen Tests besteht. Auf XML basierende Sprachen und Anwendungen haben oft DTDs, um die minimalen Standards der Wohlgeformtheit zu erweitern und zum Beispiel eine gewisse Ordnung von Elementen und Textdaten sicherzustellen. Zum Beispiel gibt es vom W3C eine DTD, die XHTML beschreibt. XHTML ist die XML-konforme Art von HTML. Die DTD von XHTML enthält eine Aufzählung aller erlaubten Elemente, wo sie stehen dürfen und was sie enthalten können. Es wäre grammatikalisch korrekt, ein <p>-Element innerhalb eines <body> zu setzen, aber dasselbe <p> hat zum Beispiel nichts innerhalb von <head> verloren. Und wagen Sie bitte nicht einmal daran zu denken, ein Element <Peanuts> zu verwenden: Es ist in der DTD nicht deklariert. (Anmerkung: Wenn Sie darauf bestehen, daß Ihre XHTML-Seite ein Element <Peanuts> enthält, können Sie Ihre eigene DTD erzeugen. Das funktioniert am besten, indem Sie die echte DTD mit einer Entityreferenz einbinden und dann Ihre eigenen Elemente einfügen. Das Ergebnis ist kein offizielles XHTML, aber gewissermaßen eine Subklasse.) Enthält das Dokument nur einen einzigen Fehler dieser Art, dann gilt es bereits als ungültig . Es mag wohlgeformt sein, aber es ist nicht gültig in bezug auf die betreffende DTD. Dieser Grad der Genauigkeit ist oft mehr Last als Hilfe, aber wenn man es braucht, steht es zur Verfügung.

Beenden wir unsere Liste mit der Anforderung, daß ein Parser die gelesenen Daten in geeigneter Form an das Programm oder den Endbenutzer übergeben muß. Das kann auf verschiedene Art und Weise geschehen. Ein großer Teil des restlichen Buchs widmet sich der Analyse dieser unterschiedlichen Möglichkeiten. Grob lassen sich aber schon jetzt die folgenden Kategorien unterscheiden:

Eventstrom

Ein Parser kann eine Folge von Events erzeugen: Der Parser liest eine Folge von Markupzeichen und konvertiert diese in eine neue und abstraktere Folge, mit vorverarbeiteten und einfacher zu interpretierenden Daten.

Objektdarstellung

Auch der Aufbau einer Datenstruktur wird von den Parsern angeboten. Die im XML-Dokument enthaltene Information wird durch Objekte gespiegelt, die genauso verschachtelt sind wie die entsprechenden Teile des Dokuments. Vom System erfordert diese Vorgehensweise ein hohes Maß an Ressourcen. Es ist aber oft erheblich einfacher und angenehmer, so zu arbeiten, weil man nach Belieben in dem erhaltenen Baum hin und her springen kann und nicht von Daten abhängig ist, die erst noch gelesen werden müssen.

Hybride Formen

Die dritte Art der Ausgabe könnten wir als »hybrid« bezeichnen. Sie wird von Parsern beherrscht, die versuchen, mittels einer eingebauten Intelligenz einen gewissen Teil des Dokuments zu identifizieren, und dann ein Objekt aufbauen, das nur diesen speziellen Teil enthält.

Beispiel: Prüfung auf Wohlgeformtheit

Bisher haben wir XML-Parser nur sehr abstrakt beschrieben, jetzt sollten wir uns auch einmal die Hände schmutzig machen. Wir werden unseren eigenen Parser schreiben, der einzig und allein prüfen soll, ob ein Dokument wohlgeformtes XML enthält. Einfacher kann ein Parser nicht sein, er betreibt keinerlei Weiterverarbeitung und liefert als Ergebnis ein einfaches »Ja« oder »Nein«.

Wir möchten damit zwei Dinge demonstrieren. Zum einen möchten wir ein wenig den Schleier des Mystischen von der XML-Verarbeitung nehmen – letzten Endes ist es doch auch nur Arbeit mit Textdaten. Andererseits möchten wir aber auch zeigen, daß die Erstellung eines korrekten Parsers in Perl (oder einer anderen Programmiersprache) eine Menge Arbeit bedeutet. Dieselbe Arbeit investiert man sinnvollerweise in das Schreiben interessanterer Quelltexte, indem man eines der vielen Perl-Module benutzt, die einen XML-Parser zur Verfügung stellen. Aus diesem Grund werden auch wir nur einen Bruchteil eines echten, in Perl geschriebenen XML-Parsers implementieren.

Achtung! Dieses Programm ist zum Spielen gedacht. Bitte benutzen Sie es dafür nach Herzenslust. Aber kommen Sie auf keinen Fall auf den Gedanken, es für ernsthaftere Dinge einzusetzen! Dies ist keine echte Lösung für die Arbeit mit Perl und XML, sondern eine Illustration dessen, was ein Parser tun kann. Das Beispiel ist unvollständig und liefert unter Umständen falsche Ergebnisse, wie wir später noch zeigen werden. Aber keine Sorge, der Rest dieses Buchs ist wirklichen XML-Parsern gewidmet, die man in Perl auch verwenden kann.

Das Programm enthält im wesentlichen eine Schleife, in der mit regulären Ausdrücken versucht wird, die verschiedenen Teile des XML-Markup zu erkennen und aus dem Text zu extrahieren. Die Schleife wird so lange durchlaufen, bis kein Text mehr entfernt werden kann. In diesem Fall ist das Dokument wohlgeformt. Falls dagegen keiner der regulären Ausdrücke passenden Text findet, ist das Dokument nicht wohlgeformt. Ein paar andere Tests können den Parser ebenfalls unterbrechen, z. B. wenn ein End-Tag gefunden wird, das nicht dem aktuellen Start-Tag entspricht. Wie schon gesagt, es ist keine echte Lösung, aber es vermittelt eine Idee davon, wie ein Parser arbeiten könnte.

Das Beispiel unten ist eine Funktion, die einen String mit XML-Text analysiert, auf Wohlgeformtheit prüft und dann einen entsprechenden Booleschen Wert als Ergebnis liefert. Wir haben einige Variablen mit Mustern eingeführt, um das Verständnis der regulären Ausdrücke zu erleichtern. Zum Beispiel enthält der String $ident einen regulären Ausdruck, der einen Bezeichner von XML erkennt. Solche Bezeichner sind Element- und Attributnamen oder die Targets von Steueranweisungen.

Beispiel: Ein rudimentärer XML-Parser

sub ist_wohlgeformt {
     my $text = shift; # zu prüfender XML-Text     
       
     # Verwendete Muster
     my $ident = '[:_A-Za-z][:A-Za-z0-9\-\._]*'; # Bezeichner (Identifier)
     my $optsp = '\s*'; # optionales Leerzeichen
     my $att1 = "$ident$optsp=$optsp\"[^\"]*\""; # Attribut mit doppelten Anführungszeichen
     my $att2 = "$ident$optsp=$optsp'[^']*'"; # Attribut mit einfachen Anführungszeichen
     my $att = "($att1|$att2)"; # beliebiges Attribut
       my @elements = (); # Stack mit offenen Elementen
       
     # In einer Schleife den String durchlaufen und XML-Markup extrahieren
     while( length($text) ) {
       
          # Ist es ein leeres Element?
          if( $text =~ /^&($ident)(\s+$att)*\s*\/>/ ) {
          $text = $';
            
          # Ist es das Start-Tag eines Elements?
          } elsif( $text =~ /^&($ident)(\s+$att)*\s*>/ ) {
          push( @elements, $1 );
          $text = $';
          # Ist es das End-Tag eines Elements?
          } elsif( $text =~ /^&\/($ident)\s*>/ ) {
          return unless( $1 eq pop( @elements ));
          $text = $';

          # Ist es ein Kommentar?
          } elsif( $text =~ /^&!--/ ) {
          $text = $';
          # Rest des Kommentars entfernen
          if( $text =~ /-->/ ) {
          $text = $';
          return if( $` =~ /--/ ); # Kommentare dürfen kein '--' enthalten
          } else {
          return;
          }
          
          # Ist es ein CDATA-Abschnitt?
          } elsif( $text =~ /^&!\[CDATA\[/ ) {
          $text = $';
          # Rest des CDATA-Abschnitts entfernen
          if( $text =~ /\]\]>/ ) {
          $text = $';
          } else {
          return;
          }
          
          # Ist es eine PI?
          } elsif( $text =~ m|^&\?$ident\s*[^\?]+\?>| ) {
          $text = $';
          # Sind es zusätzliche Leerzeichen?
          # (zum Beispiel außerhalb des Wurzelelements)
          } elsif( $text =~ m|^\s+| ) {
          $text = $';
     
          # Sind es Textdaten?
          } elsif( $text =~ /(^[^&&>]+)/ ) {
          my $data = $1;
          # Textdaten sind nur innerhalb eines Elements erlaubt
          return if( $data =~ /\S/ and not( @elements ));
          $text = $';
          
          # Ist es eine Entityreferenz?
          } elsif( $text =~ /^&$ident;+/ ) {
          $text = $';
          
          # Nein, es ist etwas Unerwartetes
          } else {
          return;
          }
     }
     return if( @elements ); # Der Stack sollte jetzt leer sein.
     return 1;
}

Die Arrays von Perl sind unter anderem deshalb so nützlich, weil man mit ihnen wesentlich abstraktere Konzepte der Informatik realisieren kann. (Anmerkung: Algorithmen mit Perl von Jon Orwant, Jarkko Hietaniemi und John Macdonald (O'Reilly Verlag) enthält ein ganzes Kapitel zu diesem Thema.) In diesem Beispiel benutzen wir eine Datenstruktur namens Stack . Letzten Endes handelt es sich dabei einfach um ein Array, das wir allerdings nur mit push( ) und pop( ) bearbeiten. Elemente werden nach dem Prinzip »last in, first out« (LIFO) gelesen: Das zuletzt auf den Stack geschobene Element wird als erstes wieder entfernt. In unserem Fall ist das eine bequeme Möglichkeit, die Namen der aktuell offenen Elemente im Gedächtnis zu behalten. Das als nächstes zu schließende Element ist stets das zuletzt geöffnete. Wenn wir ein Start-Tag finden, schieben wir es auf den Stack. Wenn wir ein End-Tag finden, holen wir das letzte Start-Tag vom Stack und vergleichen die beiden. Die Wohlgeformtheitsregeln verlangen, daß Start-Tag und End-Tag übereinstimmen.

Der Stack repräsentiert die an einer gegebenen Stelle des XML-Dokuments offenen Start-Tags, vom Wurzelelement bis zum aktuell verarbeiteten Element. Elemente werden in der Reihenfolge verarbeitet, in der sie auch im Dokument erscheinen. Betrachtet man das Dokument als einen Baum, dann sieht es so aus, als ginge man vom Stamm aus zum Ende des ersten Zweigs, dann zurück zur letzten Abzweigung, zum Ende des nächsten Zweigs und so weiter. Man bezeichnet dieses Prinzip als Depth-first (zuerst in die Tiefe). Dabei handelt es sich um die kanonische Weise, ein XML-Dokument zu verarbeiten.

Es gibt ein paar wenige Stellen, an denen wir die einfache Schleife um zusätzliche Tests erweitern. Zum Beispiel ist die Prüfung eines Kommentars etwas komplizierter, weil wir ausschließen wollen, daß der Kommentar im Inneren die Zeichen --

  • Ein Bezeichner, zum Beispiel ein Element- oder Attributname, ist nicht korrekt (Beispiele: 12bla, -fasel oder .. ).
  • Außerhalb des Wurzelelements befinden sich Textdaten, die nicht nur aus Leerzeichen bestehen.
  • Ein End-Tag stimmt nicht mit dem letzten geöffneten Start-Tag überein.
  • Ein Attributwert fehlt, oder wird ohne Anführungszeichen angegeben, oder einfache und doppelte Anführungszeichen sind vermischt.
  • Bei einem leeren Element fehlt der schließende Slash (/ ).
  • Textdaten enthalten ein ungültiges Zeichen, zum Beispiel ein einzelnes Ampersand (&) oder ein Kleiner-Zeichen (<).
  • Eine anderweitig ungültige Markupanweisung wird gefunden. Beispiele sind etwa <blubb< oder < ?blobb?>.

Probieren Sie doch ruhig einmal ein paar Grenzfälle mit Hilfe des Parsers aus. Wir machen dazu einige Vorschläge. Das kürzeste wohlgeformte XML-Dokument ist vermutlich:

 <:-/> 

Das nächste Dokument sollte eine Fehlermeldung bewirken. (Tip: Schauen Sie mal auf das End-Tag von <nachricht>.)

<memo>
   <an>mich selbst</an>
   <nachricht>Vergiß nicht, den Wagen zu mähen und
   den Rasen zu waschen.<nachricht>
</memo>

Ein Dokument kann eine Menge anderer Syntaxfehler enthalten. Unser Programm findet die meisten, aber nicht alle. Zum Beispiel sollte es stets nur ein einziges Wurzelelement geben, aber unser Programm akzeptiert auch mehrere:

<root>Ich bin das einzig wahre Wurzelelement!</root>
<root>Nein, ich bin es!</root>
<root>Öh, äh...</root>

Weitere Probleme gefällig? Der Parser kann nicht mit DTDs umgehen. Für validierende Parser findet man oft zu Beginn des Dokuments die Deklaration einer DTD, möglicherweise auch einiger Entities. Mit einer eigenen, spezialisierten Syntax hätten wir eine andere Schleife aufbauen können, die nur die DTD verarbeitet und überspringt.

Der größte Fehler unseres Parsers ist aber die fehlende Auflösung von Entityreferenzen. Er prüft zwar die Syntax einer Entityreferenz, versucht aber in keinster Weise, sie durch irgendeinen Text zu ersetzen. Warum das ein Problem ist? Stellen wir uns einmal ein Entity vor, das mehr als reine Textdaten enthält. Theoretisch kann das Entity beliebigen Markup enthalten, der zum Beispiel aus einer riesengroßen externen Datei geladen wird. Entities können auch ihrerseits Entityreferenzen enthalten, um die Referenz vollständig aufzulösen, es sind also unter Umständen verschiedene Iterationsschritte erforderlich. Unser Parser prüft nicht einmal, ob die Entities deklariert sind: Das geht alleine schon deswegen nicht, weil er mit der Syntax der DTD gar nicht umgehen kann. Entities bieten eine Menge Möglichkeiten, versteckte Fehler einzuführen. Um die eben genannten Probleme zu beheben, könnten wir in etwa wie folgt vorgehen:

  1. Eine analoge Schleife wird eingeführt, die eine DTD analysiert, bevor das eigentliche Dokument verarbeitet wird. Entitydeklarationen würden geprüft und gespeichert, um eventuelle Referenzen später aufzulösen.
  2. Falls das Dokument eine DTD enthält, wird zunächst die obige Schleife aufgerufen, um eine Liste der Entitydeklarationen zu erstellen.
  3. In der Hauptschleife werden nun alle Entityreferenzen aufgelöst. Die aufgelösten Entities werden ihrerseits analysiert und geprüft, eventuelle neue Entityreferenzen werden ebenfalls aufgelöst. Dieser Prozeß kann recht verschlungen werden, mit Schleifen innerhalb von Schleifen, Rekursion oder anderen komplexen Spielereien der Programmierung.

Was als einfacher Parser begann, wird recht schnell zu einem ziemlich unübersichtlichen, komplexen Ding. Wir sehen daran zwei Dinge: Die Theorie eines XML-Parsers ist relativ leicht zu verstehen, aber die Praxis wird trotzdem recht kompliziert. Diese Übung hatte den Sinn, einige Probleme beim Parsen eines XML-Dokuments zu demonstrieren, aber kommen Sie bitte keinesfalls auf die Idee, mit derlei Dingen fortzufahren. Ganz im Gegenteil, wir raten Ihnen ausdrücklich, die ausgiebige Arbeit zu nutzen, die jemand anderes bereits geleistet hat, um Parser zu produzieren. Verlassen wir das dunkle Zeitalter und begeben uns in die glücklichere Ära der fertigen Parser.

  

  

<< 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