Das Einfügen von externen Dateien in XML-Dokumente gestaltete sich bisher umständlich. Oftmals musste der Umweg über Entities oder über XLink mithilfe des embed-Attributs gegangen werden. Mit dem neuen Standard XInclude des W3-Konsortiums steht jetzt eine einfache Sprache für das Einfügen und Zusammenführen von Dateien zur Verfügung.
Kurz vor Weihnachten 2004 hat das W3-Konsortium den Standard XML Inclusion [1] verabschiedet, der abgekürzt XInclude genannt wird. Ziel dieser auf XML basierenden Sprache ist es, ein Verfahren festzulegen, wie bestehende Dateien in ein XML-Dokument eingefügt oder mehrere Dateien zu einem einzigen Dokument zusammengeführt werden können. XInclude ist eine einfache Sprache, die im Prinzip nur aus zwei Elementen besteht.
xi:include
Das Element
xi:include gibt die einzufügende Datei in Form eines URI an. Listing 1 zeigt ein einfaches praktisches Beispiel. In eine bestehende XML-Datei wird eine XML-Datei eingefügt. Listing 2 enthält die einzufügende XML-Datei.
Listing 1 <?xml version="1.0" encoding="iso-8859-1"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">
<text>Hier folgt der Disclaimer:</text>
<xi:include href="disclaimer.xml"/>
</document>
Listing 2 <?xml version="1.0" encoding="iso-8859-1"?>
<text>
Eine Haftung für die Richtigkeit der veröffentlichten Artikel kann durch die Redaktion von Soft- und Hardware Service nicht übernommen werden. Für Schäden, einschließlich jeglicher genereller, spezieller, zufälliger oder Folgeschäden, die aus den Artikeln und Beiträgen resultieren, übernehmen die Autoren oder Soft- und Hardware Service keine Haftung.
</text>
Das Wurzelement
document enthält den Namensraum für XInclude. Das empfohlene Präfix ist
xi und der URI lautet
http://www.w3.org/2001/XInclude. Eine XML-Datei wird über das Element
xi:include eingebunden. Über das Attribut
href wird direkt der Dateiname (eventuell inklusive Pfad) angegeben. Wird diese Datei von einem XML-Parser geparst, der XInclude unterstützt, lädt dieser die XML-Datei und fügt den Inhalt der geladenen Datei an die Stelle des
xi:include-Elements ein. Interessant ist jetzt, wie die sich ergebende XML-Datei aussieht. Listing 3 zeigt die komplette XML-Datei mit dem Inhalt der Datei
disclaimer.xml. Wie Sie dem Listing 3 entnehmen können, wird in der XML-Datei das
xi:include Element durch das Wurzelelement der eingefügten Datei ersetzt.
Listing 3 <?xml version="1.0" encoding="iso-8859-1"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">
<text>Hier folgt der Disclaimer:</text>
<text xml:base="disclaimer.xml">
Eine Haftung für die Richtigkeit der veröffentlichten Artikel kann durch die Redaktion von Soft- und Hardware Service nicht übernommen werden. Für Schäden, einschließlich jeglicher genereller, spezieller, zufälliger oder Folgeschäden, die aus den Artikeln und Beiträgen resultieren, übernehmen die Autoren oder Soft- und Hardware Service keine Haftung.
</text>
</document>
Statt einer XML-Datei kann auch eine Text-Datei eingebunden werden. Auch hier wird dann das
xi:include-Element durch den Inhalt der Text-Datei ersetzt. Da die Text-Datei ja über keine XML-Elemente verfügt, müssen entsprechende Elemente vor dem
xi:include-Element gesetzt werden:
<text>Hier folgt der Disclaimer:</text>
<text>
<xi:include href="disclaimer.txt" parse="text" encoding="iso-8859-1"/>
</text>
Bei einer Text-Datei sollte über das
encoding-Attribut die Kodierung des Textes angegeben werden, weil die Kodierung der Text-Datei nicht so leicht ermittelt werden kann, während bei XML-Dateien das
encoding-Attribut im Prolog eingesetzt wird. Standardmäßig wird UTF-8 erwartet. Über das
parse-Attribut wird festgelegt, dass der eingebundene Text nicht als XML, sondern als Text geparst werden soll. Auch eine XML-Datei lässt sich so als Text einfügen:
<xi:include href="disclaimer.xml" parse="text" encoding="iso-8859-1"/>
Dabei werden die spitzen Klammern und die Zeilenumbrüche entsprechend kodiert (
< >
).
xi:fallback
Das Element
xi:fallback kann nur innerhalb von
<xi:inlcude> ... <xi:include> eingesetzt werden und wird dann ausgeführt, wenn die Datei im
href-Attribut nicht geladen werden konnte:
<xi:include href="disclaimer.xml" parse="xml" encoding="iso-8859-1"><br></br> <xi:fallback>
<error>xinclude error: Datei nicht gefunden</error>
</xi:fallback>
</xi:include>
Das Element
xi:fallback verfügt über keinerlei Attribute. Der Inhalt des Elements sollte aus weiteren Elementen bestehen, die dann in der XML-Datei eingefügt werden, wenn die einzubindende Datei nicht geladen werden kann.
Mehrere Dokumente zusammenführen
Innerhalb einer XML-Datei können beliebig viele
xi:include-Elemente verwendet werden, um so mehrere XML-Dateien zu einer XML-Datei zusammenzuführen:
<xi:include href="header.xml" parse="xml" encoding="iso-8859-1">
<xi:fallback>
<error>xinclude error: Datei nicht gefunden</error>
</xi:fallback>
</xi:include>
<xi:include href="disclaimer.xml" parse="xml" encoding="iso-8859-1">
<xi:fallback>
<error>xinclude error: Datei nicht gefunden</error>
</xi:fallback>
</xi:include>
<xi:include href="copyright.xml" parse="xml" encoding="iso-8859-1">
<xi:fallback>
<error>xinclude error: Datei nicht gefunden</error>
</xi:fallback>
</xi:include>
<xi:include href="footer.xml" parse="xml" encoding="iso-8859-1">
<xi:fallback>
<error>xinclude error: Datei nicht gefunden</error>
</xi:fallback>
</xi:include>
Einzelne Elemente einfügen
Oftmals besteht der Wunsch, kein komplettes XML-Dokument einzufügen, sondern nur ein bestimmtes Element aus diesem Dokument. Dazu könnte man natürlich mithilfe eines DOM-Parsers das Dokument parsen und das gewünschte Element als Knoten in ein anderes XML-Dokument importieren. Dieser umständliche Weg kann durch XInclude wesentlich verkürzt werden. XInclude verwendet dazu die XPointer-Spezifikation [2], sodass ein bestimmtes Element gezielt eingefügt werden kann.
XPointer spricht ein Element anders als XPath nicht über den Elementnamen, sondern über den Wert des vergebenen
id-Attributs an. Dazu ist es erforderlich, dass in der XML-Datei, von der ein Element in ein anderes Dokument eingefügt werden soll, eine DTD- bzw. Schema-Datei vorhanden ist, die das
id-Attribut für das Element definiert. Über das Attribut
xpointer innerhalb von
<xi:include> wird das
id-Attribut des einzufügenden Elements angegeben:
<xi:include href="datei1.xml" parse="xml" xpointer="headline1">
Bei dem Einsatz von XPointer sollte das Attribut
parse auf
xml gesetzt sein.
Unterstützung von XInclude in aktuellen Programmiersprachen und XML-Parsern
Als erster eigenständiger XML-Parser unterstützt libxml [3] den XInclude-Standard. Der Parser wird u.a. von PHP 4.x und 5.0.x [4] verwendet. Seit PHP 4.3.0 wird XInclude und PHP 5.0.x unterstützt, und zwar über die Methode
xinclude() der Klasse
DomDocument. Diese Methode ist kein DOM-Standard. Der Code für PHP 4.3.x in Listing 4 lädt und parst die XML-Datei aus Listing 1 und veranlasst anschließend den Parser, die XInclude-Anweisungen auszuführen. Der Parser produziert das XML-Dokument aus Listing 3. Für PHP 5 wird ebenfalls die Methode
xinclude() der Klasse
DomDocument verwendet, jedoch wird in PHP 5 eine XML-Datei anders geladen als in PHP 4.x (s. Listing 5). Die Details dazu können hier nicht angesprochen werden. Der interessierte Leser sei auf [5] verwiesen.
Listing 4 <?php<br></br> if(!$dom=domxml_open_file(dirname(__FILE__)."/incl.xml")) {
exit ("Fehler beim Parsen");
}
$dom->xinclude();
print(htmlentities($dom->dump_mem()));
?>
Listing 5 <?php
$dom = new DomDocument();
$dom->load("incl.xml");
if(!$dom) {
exit ("Fehler beim Parsen");
}
$dom->xinclude();
$str=$dom->savexml();
print ($str);
?>
Der Xerces-Parser in der Java-Fassung unterstützt ebenfalls XInclude und ist Bestandteil der JAXP-API (Java API für XML Processing). Derzeit kann jedoch nur die Xerces-Version verwendet werden, die in J2SE 5.0 [6] enthalten ist oder die davon entbundelte Version [7] auf java.net. Der Download einer Xerces-Version mit XInclude-Support über die Seiten der Apache Software Foundation [8] ist derzeit noch nicht möglich, wird aber in absehbarer Zeit verfügbar sein. JAXP 1.3 unterstützt XInclude direkt. Der Artikel auf Seite 22-27. in diesem Heft beschreibt die Neuerungen in JAXP 1.3 sowie die Anwendung von XInclude innerhalb von Java.
Microsofts .NET-Framework unterstützt in den Versionen 1.0 und 1.1 kein XInclude. Oleg Tkachenko hat dazu ein eigenes Projekt XInclude.NET [9] ins Leben gerufen, das mittlerweile in das Open-Source-Projekt MVP [10] bei Sourceforge integriert wurde. Wie in Java oder PHP kann die XML-Datei mit den XInclude-Elementen als DOM-Dokumentenbaum vorliegen:
XmlReader reader = new XIncludingReader(new XmlTextReader("incl.xml"));
XmlDocument doc = new XmlDocument();
doc.Load(reader);
Dazu existiert die Klasse
XIncludingReader, an die ein Objekt der Klasse
XMLTextReader übergeben werden kann. Anschließend wird ein leeres DOM-Dokument erzeugt und über die
Load()-Methode die XML-Datei mit den XInclude-Elementen geladen. Anschließend kann der sich ergebende Dokumentenbaum ausgegeben oder angezeigt werden.
Für die Sprache Perl hat Matt Sergeant, der auch viele weitere Module für die Arbeit mit XML erstellt hat, einen XInclude-Support als einfachen SAX-Filter unter dem Modulnamen XML-Filter-XInclude-1.0 [11] erstellt. Die Ausführung der XInclude-Anweisungen erfolgt direkt beim Parsen über die
parse()-Methode:
my $parser = XML::SAX::ParserFactor->parser(
Handler => XML::Filter::XInclude->new(
Handler => XML::SAX::Writer->new
)
);
$parser->parse_uri("incl.xml");
Das Element xi:include
Das Element gibt das einzubindende Dokument an und hat diese allgemeine Form:
<xi:include href="url" parse="xml | text" xpointer="id" encoding="charset" accept="mime-type" accept-langauge="language">
Das Element verfügt über diese Attribute:
href: gibt einen URI an, unter dem das einzubindende Dokument verfügbar ist.
parse: gibt an, ob das Dokument als XML-Dokument (Wert ist
xml) oder als Text-Dokument (Wert ist
text) eingefügt werden soll.
xpointer: gibt den Wert des
id-Attributs des XML-Elements an, das eingefügt werden soll.
encoding: gibt bei Text-Dokumenten die Kodierung des Textes an, z.B. iso-8859-1.
accept: gibt den MIME-Typ an, für XML-Dateien text/xml, für Text-Dateien plain/text.
accept-language: gibt die verwendete Sprache gemäß RFC 2616 [12] an, z.B. de-DE.
Das Element xi:fallback
Das Element kann nur innerhalb von
<xi:include> ... <xi:include> verwendet werden und wird dann ausgeführt, wenn der in
<xi:include> angegebene URI nicht gefunden werden konnte. Das Element verfügt über keine Attribute.
Links und Literatur