Perl und XML-Namensräume

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

Wir haben XML- Namensräume schon in Aktion erlebt, seit wir sie in Einführung in XML zum ersten Mal erwähnt haben. Eine Reihe von XML-Anwendungen (unter anderem XSLT oder SOAP) bestehen darauf, daß alle ihre Elemente in einem definierten Namensraum liegen. Ob das sinnvoll ist oder nicht, hängt wohl vor allem davon ab, wie symbiotisch eine Anwendung ist: Wenn sie eher alleine arbeitet und mit einem einzigen Dokument, haben Namensräume keinen großen Sinn. Sind die verarbeiteten XML-Dokumente aber statt dessen stets mit Fragmenten anderer Anwendungen gefüllt, dann sieht das schon anders aus.

DocBook XML ist ein nicht besonders symbiotisches Beispiel. Eine Instanz eines DocBook-Dokuments ist meistens ein vollständiges XML-Dokument. Der Inhalt ist ein abgeschlossenes Buch oder ein abgeschlossener Artikel. Alle erlaubten Elemente innerhalb eines solchen Dokuments, die nicht explizit einem bestimmten Namensraum zugeordnet sind, sollten in der offiziellen DocBook-Dokumentation zu finden sein. Andererseits ist es nicht ungewöhnlich, in ein DocBook-Dokument eine Reihe von MathML-Elementen einzubetten, die sich wie Parasiten in die normalen DocBook-Elemente integrieren.

Diese Vorgehensweise ist aus zwei Gründen nützlich: Zum einen kann sich DocBook damit begnügen, mit seinen Elementen alle Bedürfnisse eines Autors technischer Dokumentation abzudecken. Man würde die Sprache überfrachten, wenn sie zusätzlich all die ausgetüftelten Feinheiten einer mathematischen Gleichung enthalten sollte. (Zwar gibt es ein <equation>-Element, das aber eher eingesetzt wird, um den Inhalt einer darin eingebetteten Grafik zu beschreiben.) Nehmen wir dagegen MathML hinzu, dann können wir alle Möglichkeiten dieser Sprache innerhalb eines DocBook-Dokuments ausreizen. Durch den eigenen Namensraum sind Kollisionen ausgeschlossen. (MathML und DocBook verstehen sich so gut, daß die DocBook-DTD dem Benutzer die Einbindung eines »MathML-Moduls« erlaubt. Dieses Plugin definiert ein neues Element <mml:math>. Innerhalb dieses Elements gilt die DTD von MathML, die vom Plugin eingebunden wird. Wenn das Dokument validiert wird, gilt mal die DocBook-DTD und mal die von MathML.

Zweitens kann man Namensräume als eine Art von Konsulat oder Botschaft betrachten. Während man sich auf ihrem Grund und Boden (bzw. innerhalb ihres Geltungsbereichs) aufhält, gelten die Regeln des betreffenden Landes, unabhängig davon, in welchem Gastgeberland man sich befindet. XML-Namensräume haben auch eine gewisse Ähnlichkeit mit den Namensräumen von Perl, die die Separierung und Verwendung von Variablen, Subroutinen und anderen Symbolen aus Irgendein::Anderes::Package ermöglichen (natürlich nur, sofern man sie nicht innerhalb des main-Package definiert).

Mit anderen Worten: Die Präsenz von Namensräumen ist ein sicheres Kennzeichen, daß eine weitere, separate XML-Anwendung im Spiel ist, die von der aktuellen Anwendung aus aufgerufen wird. Wenn Sie einen Prozessor schreiben, der eine bestimmte XML-Anwendung behandeln soll, und im voraus wissen, daß bestimmte andere Namensräume darin von Zeit zu Zeit auftauchen, dann ist es eine gute Idee, die Delegierung an ein anderes Programm zu erwägen.

Nehmen wir zum Beispiel an, auf Ihrem Rechner gäbe es eine XML-Datei mit einer Liste der in Ihrem Haus lebenden Affen. Die Datei besteht zum großen Teil aus Elementen, die Sie selber festgelegt haben. Andererseits kommen auch einige Elemente der Monkey Markup Language vor. Dabei handelt es sich um eine standardisierte Sprache zur Beschreibung von Affen in XML. Diese definiert ihren eigenen Namensraum:

<?xml version="1.0" encoding="ISO-8859-1">
<monkey-list>
    <monkey>
        <description xmlns:mm="http://www.jmac.org/projects/monkeys/mm/">
            <mm:monkey> <!-- Beschreibung eines einzelnen Affen -->
                <mm:name>Virtram</mm:name>
                <mm:color>rötlich grau</mm:color>
                <mm:favorite-foods>
                    <mm:food>Bananen</mm:food> <mm:food>Walnüsse</mm:food>
                </mm:favorite-foods>
                <mm:personality-matrix>
                    F6 30 00 0A 1B E7 9C 20
                </mm:personality-matrix>
            </mm:monkey>
        </description>
        <location>Wohnzimmer</location>
        <job>Vogelscheuche</job>
    </monkey>
    <!-- Hier kommen die anderen Affenbeschreibungen -->
</monkey-list>

URI-Bezeichner

Viele XML-Technologien, z. B. der XML-Namensraum, SAX2 oder SOAP, basieren auf URIs als eindeutigen Bezeichnern. Ein URI ist ein String, der für etwas anderes steht: ein Feature, eine Property oder dergleichen. Die Bedeutung des URI liegt in der Absprache: Der Autor eines Standards oder einer Software legt fest, was er zu sagen hat und der Anwender verläßt sich dann darauf. URIs sehen oft wie URLs aus, meistens beginnen sie mit http://. Das bedeutet, daß man sie in einen Browser eingeben kann, um zu sehen, was passiert. Mit Sicherheit wird das Ergebnis aber oft ein enttäuschender HTTP-Fehlercode 404 (Dokument nicht gefunden) sein. Die Aufgabe eines URI ist nicht das Auffinden einer Ressource, sondern die globale Eindeutigkeit.

Entwickler, die einen neuen URI definieren, gehen daher gern wie folgt vor: Man nimmt einen Webserver oder sogar ein Verzeichnis eines Webservers, das man garantiert unter Kontrolle hat. An dieses Verzeichnis werden dann Begriffe angehängt, die einerseits sagen, wofür der URI steht, und die zweitens die Eindeutigkeit (jetzt aber nur noch innerhalb dieses Webservers oder Verzeichnisses) sichern müssen. Wenn Sie zum Beispiel das Verzeichnis "http://www.greenmonkey-markup.com/~jmac" kontrollieren, wäre "http://www.greenmonkey-markup.com/~jmac/monkeyml/" ein guter URI. Egal, ob sich dahinter ein echtes Dokument verbirgt oder nicht, außer Ihnen selbst kann niemand auf die Idee kommen, einen solchen URI zu erzeugen. Höfliche Entwickler sorgen dafür, daß sich hinter dem URI tatsächlich etwas Sinnvolles verbirgt, zum Beispiel Dokumentation über die Technologie, eine DTD, ein XML-Schema oder dergleichen.

Eine andere Lösung ist die Verwendung eines Service wie PURL (hat nichts mit Perl zu tun), der die Vergabe einer als URI zu verwendenden URL ermöglicht, die dann auf andere (und möglicherweise variable) URLs umgelenkt wird.

Gelegentlich enthält ein URI Zusatzinformationen. Zum Beispiel sind einige XML-Prozessoren sehr pingelig in Bezug auf erlaubte und nicht erlaubte URIs. Dafür gibt es gute Gründe, wenn der URI zum Beispiel eine Versionsnummer enthält. Ein Stylesheet-Prozessor wird sorgfältig unterscheiden, ob ein XSLT-Dokument den vom W3C vergebenen URI von XSLT 1.0 oder den einer Vorgängerversion enthält.

Robin Berjons Modul XML::NamespaceSupport kann beim Umgang mit Namensräumen gute Dienste leisten.

Glücklicherweise haben wir auf unserem Rechner das hervorragende Modul XML::MonkeyML , das ein in MonkeyML geschriebenes Dokument liest und in ein Objekt übersetzt. Dieses Modul kann zum Beispiel mit dem speziellen MonkeyML-Element personality-matrix umgehen. Dieses Element kondensiert die gesammelten persönlichen Eigenschaften eines Affen in einen kurzen Hexadezimalcode (zumindest in unserer Fantasie). Wir nutzen das, um vorherzusagen, wie ein Affe in einer bestimmten Situation reagieren wird:

#!/usr/bin/perl

# Das Programm erhält auf der Kommandozeile eine Affenaktion übergeben.
# Für jeden Affen in einer Liste (der Dateiname eines MonkeyML-Dokuments
# wird ebenfalls auf der Kommandozeile übergeben) wird eine Prognose der
# erwarteten Reaktion des Affen ausgegeben.

use warnings;
use strict;

use XML::LibXML;
use XML::MonkeyML;

my ($filename, $action) = @ARGV;   

unless (defined ($filename) and defined ($action)) {
   die "Usage: $0 <Datei-mit-Affenliste> <Aktion>\n";
}

my $parser = XML::LibXML->new;
my $doc = $parser->parse_file($filename);

# Sammle die Elemente mit den Affenbeschreibungen
my @monkey_nodes = $parser->documentElement->findNodes("//monkey/description/mm:monkey");

foreach (@monkey_nodes) {
   my $monkeyml = XML::MonkeyML->parse_string($_->toString);
   my $name = $monkeyml->name . " the " . $monkeyml->color . "e monkey";
   print "$name würde sich folgendermaßen verhalten:\n";
   # Die Methode 'action' des MonkeyML-Objekts prognostiziert die Reaktion
   print $monkeyml->action($action); print "\n";
}

So sieht die Ausgabe aus:

$ ./money_action.pl monkeys.xml "Gib ihm eine Banane"

Virtram, der rötlich graue Affe, würde sich folgendermaßen verhalten:
Er nimmt die Banane, ißt sie und sagt "Ugh".

Da wir gerade über Faulheit reden: Schauen wir uns doch einmal an, wie ein Hilfsmodul im Stil von XML::MonkeyML aussehen könnte.

  

  

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