XML::LibXML

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

Das Modul XML::LibXML von Matt Sergeant ist eine Schnittstelle zur LibXML-Bibliothek aus dem GNOME-Projekt. Diese DOM-Implementierung hat sich schnell verbreitet, weil sie die Geschwindigkeit der alten auf XML::Parser basierenden Module mit einer vollständigen Implementierung von DOM 2 verbindet. Insbesondere werden also Namensräume unterstützt.

Wir haben uns bis jetzt nicht viel mit Namensräumen beschäftigt. Tatsächlich hört man nach wie vor oft den Rat, sie zu vermeiden. Sie führen zu erhöhter Komplexität von Markup und Quelltext, da man sowohl lokale Namen als auch die URIs der Namensräume berücksichtigen muß. Trotzdem werden Namensräume in XML zunehmend wichtig, und früher oder später müssen wir uns damit beschäftigen – ob wir wollen oder nicht. Zum Beispiel verwendet die Transformationssprache XSLT Namensräume für die Unterscheidung zwischen Instruktions-Tags und Daten, d. h. zwischen Elementen, die die Ausgabe kontrollieren, und denjenigen, die die eigentliche Ausgabe darstellen.

Selbst im guten alten HTML findet man Namensräume. Namensräume bieten eine gute Möglichkeit, spezialisierten Markup in eigene Dokumente einzubinden, zum Beispiel mathematische Gleichungen in normale HTML-Seiten. Das leistet zum Beispiel die Sprache MathML. Das folgende Beispiel demonstriert, wie man MathML und seinen Namensraum einbindet.

Beispiel: Ein Dokument mit Namensräumen

<?xml version="1.0" encoding="ISO-8859-1"?>
<html>
    <body xmlns:eq="http://www.w3.org/1998/Math/MathML">
        <h1>Der Hauptsatz von Molly</h1>
        <p>
            Es ist allgemein bekannt, daß Katzen ihren eigenen Willen haben. Man wird eine
            Katze nie dazu bringen, sich auf einer Geraden zu bewegen, es sei denn, sie will
            es von selbst. Zwingt man eine Katze trotzdem, sich auf einer Geraden zu bewegen,
            dann steigt die Wahrscheinlichkeit, daß sie einem ins Gesicht springt, um von der
            Geraden abzuweichen, proportional zum Quadrat der Distanz der Entfernung.</p>
        <p>
            <!-- P = 1 - 1/(x^2) -->
            <eq:math>
                <eq:mi>P</eq:mi><eq:mo>=</eq:mo><eq:mn>1</eq:mn><eq:mo>-</eq:mo>
                <eq:mfrac>
                    <eq:mn>1</eq:mn>
                    <eq:msup>
                        <eq:mi>x</eq:mi>
                        <eq:mn>2</eq:mn>
                    </eq:msup>
                </eq:mfrac>
            </eq:math>
        </p>
    </body>
</html>

Die Tags mit dem Präfix eq: sind ein Teil des durch den URI "http://www.w3.org/1998/Math/MathML" identifizierten Namensraums. Der Namensraum wird in einem Attribut des <body>-Elements deklariert. Die Benutzung eines Namensraums erlaubt dem Browser die Unterscheidung zwischen normalem HTML und den Tags von MathML. Browser, die MathML verstehen, geben die qualifizierten Elemente an ihre Formatierungseinheit für mathematische Gleichungen weiter und nicht an die für normales HTML.

Es gibt allerdings auch Browser, die durch die Tags von MathML verwirrt werden und unvorhersagbare Ergebnisse produzieren. Aus diesem Grund ist es sehr nützlich, ein kleines Werkzeug zu haben, das Elemente mit qualifizierten Namensräumen entdeckt und entfernt und nur die für ältere HTML-Prozessoren geeigneten Elemente stehen läßt. Das folgende Beispiel erledigt das mit Hilfe von DOM 2. Es durchläuft das ganze Dokument und entfernt alle Elemente mit einem Namensraumpräfix.

Als ersten Schritt müssen wir die Datei lesen:

use XML::LibXML;

my $parser = XML::LibXML->new( );
my $doc = $parser->parse_file( shift @ARGV );

Als nächstes suchen wir nach dem Wurzelelement des Dokuments und geben es in eine rekursive Funktion ein, die die qualifizierten Elemente entfernt. Abschließend geben wir das Dokument wieder aus:

my $mathuri = 'http://www.w3.org/1998/Math/MathML';
my $root = $doc->getDocumentElement;
&purge_nselems( $root );
print "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n",
      $doc->toString;

Die folgende Funktion erhält als Argument einen Elementknoten. Falls der Knoten ein Namensraumpräfix enthält, wird das Element aus der Knotenliste seines Vaters entfernt. Anderenfalls ruft die Funktion sich selbst rekursiv für die Kindelemente auf:

sub purge_nselems {    
   my $elem = shift;
   return unless( ref( $elem ) =~ /Element/ );
   if( $elem->prefix ) {
      my $parent = $elem->parentNode;
      $parent->removeChild( $elem );
   } elsif( $elem->hasChildNodes ) {
      my @children = $elem->getChildnodes;
      foreach my $child ( @children ) {
     &purge_nselems( $child );
    }
  }
}

Vielleicht ist Ihnen aufgefallen, daß diese DOM-Implementierung einige Perl-typische Annehmlichkeiten bietet, die in der offiziellen DOM-Schnittstelle so nicht vorgesehen sind. Zum Beispiel liefert die Methode getChildnodes in einem Arraykontext eine normale Perl-Liste statt des etwas umständlicheren NodeList-Objekts. In einem skalaren Kontext hätte die Methode die Anzahl der Kindknoten geliefert, NodeList en werden also tatsächlich gar nicht verwendet.

Solche Vereinfachungen sind in der Welt von Perl üblich, ohne daß es jemanden stören würde. Die Betonung liegt im allgemeinen eher auf der leichten Anwendbarkeit und weniger auf der formalen Strenge. Es bleibt zu hoffen, daß eventuelle zukünftige DOM-Implementierungen in der Perl-Welt dieselben Konventionen übernehmen. Aus diesem Grund werden derlei Dinge ausführlich auf der Mailing-Liste perl-xml diskutiert. Zur Zeit findet eine Diskussion darüber statt, wie man SAX2 und seine Namensräume in einer logischen und doch Perl-typischen Weise einbindet.

Matt Sergeant hat noch einige andere Bonbons in sein XML::LibXML-Paket gelegt. Zum Beispiel kennt die Node-Klasse eine Methode findnodes( ), die als Argument einen XPath-Ausdruck erhält und auswertet. Damit kann man bestimmte Knoten erheblich bequemer finden, als das mit der normalen DOM-Schnittstelle möglich wäre. Der Parser hat Optionen, mit denen man festlegen kann, wie pedantisch er sich verhält, ob und wie Entities aufgelöst werden und inwieweit Leerzeichen von Bedeutung sind. Darüber hinaus ist es möglich, spezielle Handler für vom Parser nicht auflösbare Entities zu verwenden. Alles in allem ist dieses Modul exzellent für die Programmierung mit DOM geeignet.

  

  

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