Auflösung externer Entities

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

Standardmäßig ersetzt der Parser alle Entityreferenzen durch die zugewiesenen Werte. Im Normalfall ist das auch genau das, was wir wollen. In Ausnahmefällen wie unserem Filterbeispiel wäre es uns aber lieber, wir könnten die Entityreferenzen stehenlassen. Wie wir gesehen haben, ist das recht einfach, indem wir eine eigene Handlermethode entity_reference( ) schreiben, die die Referenzen ausgibt, ohne sie aufzulösen. Wir wissen jedoch noch nicht, wie wir das Standardverhalten (möglicherweise leicht verändert) wiederherstellen. Der Parser möchte die Referenzen ersetzen, indem er Dateien bestimmt und ihren Inhalt in den Stream einspielt. Welche Gründe kann es geben, dieses Verhalten zu ändern, von unserem Filterbeispiel einmal abgesehen?

Es ist sehr bequem, Dokumente in mehrere Dateien aufzuspalten. Das gilt insbesondere, wenn man ein sehr großes Dokument hat. Nehmen wir zum Beispiel an, wir würden ein sehr umfangreiches Buch in XML schreiben und jedes Kapitel sollte in einer eigenen Datei stehen. Mit externen Entities geht das recht einfach, etwa so:

<?xml version="1.0"?>
<doctype book [
    <!ENTITY intro-kapitel SYSTEM "kapitel/intro.xml">
    <!ENTITY nudel-kapitel SYSTEM "kapitel/nudel.xml">
    <!ENTITY saucen-kapitel SYSTEM "kapitel/saucen.xml">
    <!ENTITY suppen-kapitel SYSTEM "kapitel/suppen.xml"> ]>
    <book>
        <title>Das Kochbuch für lange Hacker-Sessions</title>
        &intro-kapitel;
        &nudel-kapitel;
        &saucen-kapitel;
        &suppen-kapitel;
    </book>

Das vorige Filterbeispiel hätte die externen Entities einfach aufgelöst und das ganze Buch in einem Stück ausgegeben. Unser schönes Schema der Aufteilung in Kapiteldateien wäre verloren. Die Aufteilung könnte nur von Hand wiederhergestellt werden. Glücklicherweise können wir die Auflösung externer Entities selbst in die Hand nehmen, indem wir einen Handler namens resolve_entity( ) schreiben.

Dieser Handler erhält vier Properties: Name, den Entitynamen; die Bezeichner SystemId und PublicId, die angeben, wo sich die zu suchende Datei befindet; und Base, die Basis-URL für eventuelle relative URLs. Im Unterschied zu den anderen Handlern muß dieser ein Ergebnis liefern, um das weitere Verhalten des Parsers zu steuern. Der Wert undef teilt dem Parser mit, daß er die Datei ganz normal laden und verarbeiten soll. Andernfalls kann man einen Hash mit Angaben über eine alternativ zu ladende Datei zurückgeben. Dieser Hash hat denselben Aufbau wie der, den man der parse( )-Methode des Parsers übergibt. Das heißt, er kann zum Beispiel einen Schlüssel SystemId mit einem Dateinamen oder einer URL enthalten. Er kann aber auch einen Textstring enthalten, der vom Parser gelesen werden soll. Schauen wir uns das folgende Beispiel an:

sub resolve_entity {     
     my( $self, $props ) = @_;
     if( exists( $props->{ SystemId }) and
        open( ENT, $props->{ SystemId })) {
     my $entval = '<?start-file ' . $props->{ SystemId } . '?>';
     while( <ENT> ) { $entval .= $_; }
     close ENT;
     $entval .= '<?end-file ' . $props->{ SystemId } . '?>';
     return { String => $entval };
     } else {
        return undef;
     }
}

Diese Methode öffnet das eigentliche Entity und liest es in einen String. Der String wird anschließend an den Parser übergeben. Zuvor wird der String aber durch zwei PIs ergänzt, die am Anfang bzw. am Ende eingefügt werden. Diese PIs erlauben es theoretisch, die Grenzen der Datei auch später zu erkennen. Damit wäre es zum Beispiel möglich, einen weiteren Filter zu schreiben, der die verschiedenen Dokumente wieder trennt.

  

  

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