Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 7. Auflage |
<< | < | > | >> | API | Kapitel 43 - XML-Verarbeitung |
XML ist die Abkürzung für »eXtensible Markup Language«. Dabei handelt es sich um ein universelles, textbasiertes Datenformat, das hauptsächlich zur Speicherung und zum Transfer von Daten verwendet wird. XML-Dokumente sind selbst beschreibend und sowohl menschen- als auch maschinenlesbar. Außerdem sind sie interoperabel, also unabhängig von Betriebssystemen und Rechnerarchitekturen. XML ist mächtig und ausdrucksstark, gleichzeitig ist es relativ leicht zu erlernen, zu erzeugen und zu interpretieren und hat sich daher in der digitalen Welt rasant verbreitet. XML entstand durch die Weiterentwicklung des SGML-Standards unter der Führung von John Bosac. Es ist ein offener Standard des W3C-Konsortiums, dessen erste Version 1998 veröffentlicht wurde.
Mittlerweile gibt es im Umfeld von XML eine ganze Reihe weiterer Standards und es hat sich eine regelrechte Industrie rund um die Sprache entwickelt. Einige der Standards im XML-Universum sind beispielsweise:
Auch als Grundlage unternehmensspezifischer proprietärer Sprachen ist XML weit verbreitet und fast jedes Standardprogramm bietet mittlerweile Schnittstellen zum Lesen und Schreiben von XML-Daten.
Wir wollen uns zunächst ansehen, wie XML-Dokumente aussehen und welchen Aufbau sie haben. Eine Datei, die dem XML-Standard folgt, wird »XML-Dokument« genannt; das folgende Listing zeigt ein einfaches Beispiel:
001 <?xml version="1.0" encoding="iso-8859-15"?> 002 <gruss> 003 Hallo, Welt! 004 </gruss> |
Offenbar besteht das Dokument aus zwei verschiedenen Bestandteilen. Einerseits erkennen wir mit Hallo, Welt! rein textuelle Teile, die »einfach so« aufgeschrieben werden, andererseits mit <gruss> oder </gruss> befehlsartige Elemente, die in spitze Klammern gesetzt werden.
Konkret lässt sich die Syntax eines XML-Dokuments vereinfacht wie folgt angeben:
xml : [ prolog ] element element : <tag> [ ( inhalt | element+ ) ] </tag> |
Ein XML-Dokument beginnt optional mit einem Prolog, darauf folgt ein Element, das sogenannte Wurzelelement. Elemente können weitere Elemente oder Text enthalten und werden von einem öffnenden und einem schließenden Tag eingeschlossen. Wir wollen uns die einzelnen Bestandteile eines XML-Dokuments in den nächsten Abschnitten genauer ansehen.
In der ersten Zeile von Listing 43.1 sehen Sie den optionalen »Prolog«, mit dem die Datei als XML-Dokument gekennzeichnet wird. Der Prolog beginnt mit der Zeichenfolge <?xml und endet mit ?>. Er bestimmt mindestens die XML-Version (version="1.0") und besitzt optional weitere Attribute, wie beispielsweise das Encoding des Dokuments (encoding="iso-8859-15"). Wird die Encoding-Angabe weggelassen, wird als Zeichensatz UTF-8 bzw. UTF-16 angenommen.
Grundsätzlich sind alle Zeichensätze erlaubt, die von der IANA (Internet Assigned Numbers Authority) definiert wurden (siehe http://www.iana.org/assignments/character-sets). Zu den wichtigsten in unserem Sprachraum gehören windows-1252 und iso-8859-15 sowie utf-8 bzw. utf-16.
Die IANA-Encoding-Namen entsprechen nicht den Namen der Zeichensätze unter Java. Der Windows-Standardzeichensatz heißt unter Java beispielsweise cp1252, im IANA-Standard aber windows-1252. Außerdem arbeiten die Betriebssysteme und Editoren oftmals nicht mit dem XML-Standardzeichensatz UFT-8 oder UTF-16, sondern mit dem Standardzeichensatz des jeweiligen Betriebssystems. Daher empfiehlt es sich, das Encoding in jedem XML-Dokument explizit anzugeben. Andernfalls führt z.B. die Verwendung von Umlauten in der Praxis schnell zu Problemen. |
|
Jedes XML-Dokument besitzt genau ein Wurzelelement, das wiederum kein, ein oder mehrere andere Elemente enthalten kann. Jedes Element kann seinerseits Attribute haben und sowohl Text als auch weitere Unterlemente enthalten. Auf diese Weise lassen sich hierarchische, baumartige Datenstrukturen erzeugen.
Ein Element besteht aus einem öffnenden und einem schließenden »Tag«. Ein Tag hat einen festen Namen und wird in spitze Klammern gesetzt. Das öffnende Tag wird mit < und > umschlossen, das schließende Tag mit </ und >. Listing 43.1 enthält beispielsweise genau ein Element mit dem Namen gruss, das in diesem Beispiel den Text Hallo, Welt! enthält.
Das folgende Beispiel zeigt ein zweistufig hierarchisches Dokument mit dem Wurzelelement gruesse.
001 <?xml version="1.0" encoding="iso-8859-15"?> 002 <gruesse> 003 <gruss bundesland="schleswig-holstein"> 004 Moin, moin! 005 </gruss> 006 <gruss bundesland="bayern"> 007 Grüß Gott! 008 </gruss> 009 </gruesse> |
Das gruesse-Element enthält zwei gruss-Elemente und jedes gruss-Element besitzt ein bundesland-Attribut. Enthält ein Element keinen Text und keine weiteren Elemente, kann es in Kurzschreibweise geschrieben werden. Der Tagname wird dann von < und /> umschlossen:
<tag/> |
001 <?xml version="1.0" encoding="iso-8859-15"?> 002 <geschlecht> 003 <maennlich/> 004 </geschlecht> |
Elemente können eine beliebige Anzahl von Attributen besitzen, mit deren Hilfe sie konfiguriert werden können. Das gruss-Element in Listing 43.2 enthält beispielsweise das Attribut bundesland, mit dem die regionale Variante der Grußformel ausgewählt wird. Attribute werden immer im öffnenden Tag angegeben und bestehen aus einem Namen und einem Wert. Mit Attributen lassen sich spezifische Eigenschaften eines Elements genauer beschreiben.
Kommentare sind fester Bestandteil der XML-Grammatik. Sie beginnen mit der Zeichenfolge <!-- und enden mit -->. Kommentare sind nicht schachtelbar, aber sie dürfen sich über mehrere Zeilen erstrecken. Die Zeichenfolge -- ist in Kommentaren nicht erlaubt.
<!-- Kommentar --> |
001 <?xml version="1.0" encoding="iso-8859-15"?> 002 <!-- Gruss an die Welt --> 003 <gruss> 004 Hallo, Welt! 005 </gruss> |
Fester Bestandteil des XML-Universums ist die Möglichkeit, mit Hilfe einer Grammatik den strukturellen Aufbau von XML-Dokumenten zu definieren. Grammatiken werden entweder mit einer DTD (Document Type Definition) oder mit einer XSD (XML Schema Definition) beschrieben. XSD ist selbst ein umfangreicher XML-Dialekt und es lassen sich damit sehr präzise Grammatiken entwerfen. DTDs sind der ältere Standard, sie stammen im Grundsatz noch aus der SGML-Ära. Sie sind weniger aufwändig als XSDs, für viele praktische Anwendungsfälle aber ausreichend. Weil DTDs einfacher zu erlernen und zu entwerfen sind als XSDs, wollen wir uns zunächst den Umgang mit DTDs ansehen.
Zum Verständnis der folgenden Ausführungen sind zwei Begriffe bedeutsam. Ein XML-Dokument heißt »wohlgeformt« (»wellformed«), wenn es lexikalisch korrekt ist, also den im vorigen Abschnitt beschriebenen Aufbau besitzt. Ein XML-Dokument heißt »gültig« (»valid«), wenn es wohlgeformt ist UND seiner Grammatik genügt.
Damit ein XML-Dokument ordnungsgemäß verarbeitet werden kann, muss es mindestens wohlgeformt sein, eine Grammatik dagegen ist nicht zwingend erforderlich. Diese empfiehlt sich aber immer dann, wenn das Dokument komplex ist oder als Schnittstelle zwischen verschiedenen Systemen oder Personen dient. Eine explizite Grammatik stellt nicht zuletzt auch ein wichtiges Stück Dokumentation dar.
DTDs selbst sind keine XML-Dokumente, sehen auf den ersten Blick aber ein wenig so aus. Auch eine DTD beginnt beispielsweise zunächst mit einem optionalen XML-Prolog, hinter dem die Definition der Elemente und Attribute folgt. DTDs können auch Kommentare enthalten, sie haben genau den gleichen Aufbau wie Kommentare in einem XML-Dokument.
Als erstes Beispiel sehen wir uns eine DTD für Listing 43.1 an:
001 <?xml version="1.0" encoding="iso-8859-15"?> 002 <!ELEMENT gruss (#PCDATA)> |
In der ersten Zeile sehen Sie den XML-Prolog, gefolgt von der Defintion des einzigen Elements gruss. Das gruss-Element kann Text enthalten, was durch die Formulierung #PCDATA zum Ausdruck gebracht wird.
In der Elementdefinition wird festgelegt, ob das Element Text aufnehmen oder andere Elemente enthalten soll. Zudem muss zu jedem Kindelement die Häufigkeit des Auftretens festgelegt werden. Die Elementdefintion beginnt mit <!ELEMENT, gefolgt von dem Namen des Elements. Nach dem Namen folgt der mögliche Inhalt des Elements. #PCDATA signalisiert, dass das Element Text enthalten kann. Enthält das Element andere Elemente, werden diese in runden Klammern aufgezählt. Die Reihenfolge der Elemente ist dabei von Bedeutung, d.h., die Elemente müssen später in dem XML-Dokument in der festgelegten Reihenfolge auftreten. Die Defintion eines Elements endet mit >.
001 <!-- Ein oder mehrere gruss-Kinder --> 002 <!ELEMENT gruesse (gruss+)> 003 004 <!-- Kein, ein oder mehrere gruss-Kinder --> 005 <!ELEMENT gruesse (gruss*)> 006 007 <!-- Ein gruss-Kind --> 008 <!ELEMENT gruesse (gruss)> 009 010 <!-- gruss enthält einen lang- und einen kurztext --> 011 <!ELEMENT gruss (langtext, kurztext)> 012 013 <!-- Entweder maennlich oder weiblich --> 014 <!ELEMENT geschlecht (maennnlich | weiblich)> 015 016 <!-- gruss enthält Text --> 017 <!ELEMENT gruss (#PCDATA)> |
Die Häufigkeit des Auftretens jedes Elements wird durch die angehängten Symbole +, * usw. bestimmt. Ein + bedeutet, dass ein Element ein- oder mehrere Male auftreten darf, ein * steht für beliebig häufiges Auftreten und ein ? bedeutet, dass das Element entweder gar nicht oder genau einmal auftreten kann. Werden mehrere Unterelemente mit Kommata getrennt, müssen sie auch im XML-Dokument in genau dieser Reihenfolge auftreten. Werden sie mit einem senkrechten Strich getrennt, muss genau eines der aufgelisteten Elemente an der entsprechenden Stelle auftauchen.
Die Attributdefinition beginnt mit <!ATTLIST, gefolgt von dem Elementnamen, zu dem das Attribut gehört, gefolgt von dem Namen des Attributs selbst Das Schlüsselwort CDATA signalisiert, dass das Attribut beliebigen Text enthalten kann. Das Attribut kann optional (#IMPLIED) oder obligatorisch (#REQUIRED) sein. Kann ein Attribut nur eines von wenigen zuvor festgelegten Werten annehmen, werden diese in runden Klammern aufgezählt und mit | voneinander getrennt. Die Defintion des Attributs endet mit >.
Das folgende Listing zeigt die DTD von Listing 43.2.
001 <?xml version="1.0" encoding="iso-8859-15"?> 002 <!ELEMENT gruesse (gruss+)> 003 <!ELEMENT gruss (#PCDATA)> 004 <!ATTLIST gruss bundesland CDATA #REQUIRED> |
Das folgende Listing zeigt weitere Attributdefinitionen:
001 <!-- Attribut mit Defaultwert --> 002 <!ATTLIST auto anzahlreifen CDATA "4"> 003 004 <!-- Obligatorisches Attribut --> 005 <!ATTLIST gruss bundesland CDATA #REQUIRED > 006 007 <!-- Optionales Attribut --> 008 <!ATTLIST gruss bundesland CDATA #IMPLIED > 009 010 <!-- Attribut mit Auswahlliste --> 011 <!ATTLIST person geschlecht (maennlich|weiblich) "maennlich" > |
Soll ein XML-Dokument validiert werden können, muss es den Zusammenhang zur DTD selbst herstellen. Eine DTD kann entweder direkt in das XML-Dokument eingebettet sein oder als externe Datei referenziert werden. Da es in der Praxis meist üblich ist, die DTD extern zu definieren, wollen wir auf die internen DTDs an dieser Stelle nicht weiter eingehen. Das XML-Dokument verweist auf seine externe DTD im Anschluss an die Prologzeile:
001 <?xml version="1.0" encoding="iso-8859-15"?> 002 <!DOCTYPE gruss SYSTEM "gruss.dtd"> 003 <gruss> 004 Hallo, Welt! 005 </gruss> |
In der Doctype Definition wird das Wurzelelement, also das Element der höchsten Ebene, angegeben (in unserem Fall gruss). Danach folgt das Schlüsselwort SYSTEM und der Dateiname der DTD. Bevor wir uns nun der eigentlichen programmgesteuerten Verarbeitung der XML-Dokumente zuwenden, wollen wir noch kurz auf die zweite Form der XML-Grammatiken eingehen, die XML Schema Definitionen.
Die »XML Schema Definition«, kurz XSD, ermöglicht ebenfalls die Definition von XML-Grammatiken. Im Gegensatz zu DTDs sind XSD-Dateien selbst XML-Dokumente, die ihrerseits einer Grammatik folgen. Die XML Schema Definition bietet im Gegensatz zur DTD mehr Freiheitsgrade und unterscheidet diverse elementare Datentypen. Außerdem erlaubt sie es, einfache und komplexe Datentypen selbst zu definieren. Die ausführliche Beschreibung der XML Schema Definition ist für den Rahmen dieser Einführung viel zu umfangreich, wir wollen uns daher im Folgenden lediglich einige Grundlagen dieses Standards ansehen.
Eine XSD-Datei beginnt wie folgt:
<?xml version="1.0" encoding="iso-8859-15"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> ... |
Den Prolog kennen wir aus Abschnitt 43.1.1. Im schema-Wurzelelement verbinden wir den Präfix xs mit der Grammatik der XML Schema Definition. Der Name des Präfixes ist frei wählbar, meist wird xs verwendet, gelegentlich auch xsd. Der Präfix (Namensraum) wird u.a. den Elementnamen vorangestellt, gefolgt von einem :. In unserem Fall lautet der komplette Präfix also xs:.
Elemente definiert man wie folgt:
<xs:element name="name"> |
Mit dem Attribut name wird der Name des zu definierenden Elements festgelegt. Ein weiteres wichtiges, aber optionales Attribut ist type zur Definition des Datentyps des Elementinhalts.
<xs:element name="name" type="type"> |
Die XML Schema Definition bietet eine Reihe elementarer Datentypen an, von denen die wichtigsten in der folgenden Tabelle aufgeführt sind:
Name | Beschreibung |
boolean | Wahrheitswert, repräsentiert durch den Ausdruck false bzw. true oder durch die Zahlen 0 und 1 |
byte | Ein acht Bit langer Ganzzahltyp, entsprechend dem Wertebereich des Java-Datentyps byte |
date | Darstellung eines Datums, optional mit Zeitzone. Beispiel: 1972-03-03 |
dateTime | Darstellung eines Datums inkl. Zeitangabe, optional mit Zeitzone. Beispiel: 1969-07-20T03:40:00 |
double | Eine 64 Bit-Fließkommazahl nach IEEE 754, entprechend dem Wertebereich des Java-Datentyps double |
float | Eine 32 Bit-Fließkommazahl nach IEEE 754, entsprechend dem Wertebereich des gleichnamigen Java-Datentyps |
int | Eine 32 Bit-Ganzzahl, entsprechend dem Wertebereich des Java-Datentyps int |
short | Darstellung einer 16 Bit-Ganzzahl, entsprechend dem Wertebereich des gleichnamigen Java-Datentyps |
string | Darstellung einer beliebigen Zeichenkette, entsprechend dem Java-Datentyp String |
time | Darstellung einer Uhrzeitangabe. Beispiel: 23:59:59 |
Tabelle 43.1: Wichtige elementare Datentypen des XSD-Standards
001 <!-- Element mit ganzzahligem Inhalt --> 002 <element name="anzahl" type="xs:int"/> 003 004 <!-- Element mit Uhrzeit-Inhalt --> 005 <element name="abfahrt" type="xs:time"/> 006 007 <!-- Element mit Zeichenketten-Inhalt --> 008 <element name="vorname" type="xs:string"/> |
Elemente, die andere Elemente enthalten, heißen komplexe Elemente und werden wie folgt definiert:
001 <?xml version="1.0" encoding="iso-8859-15"?> 002 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 003 <xs:element name="gruesse"> 004 <xs:complexType> 005 <xs:sequence> 006 <xs:element name="gruss" type="xs:string"/> 007 </xs:sequence> 008 </xs:complexType> 009 </xs:element> 010 </xs:schema> |
In diesem Beispiel enthält das gruesse-Element genau ein gruss-Kind; im folgenden Listing kann es kein, ein oder mehrere Kinder enthalten:
001 <?xml version="1.0" encoding="iso-8859-15"?> 002 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 003 <xs:element name="gruesse"> 004 <xs:complexType> 005 <xs:sequence> 006 <xs:element name="gruss" type="xs:string" 007 minOccurs="0" maxOccurs="unbounded"/> 008 </xs:sequence> 009 </xs:complexType> 010 </xs:element> 011 </xs:schema> |
Die Attribute maxOccurs und minOccurs haben die Voreinstellung 1. Statt in einem sequence-Element können Sie die Kindelemente auch mit einem all- (beliebige Reihenfolge der Kindelemente) oder choice-Element (nur ein Kindelement) umschließen.
Elemente, die Attribute enthalten, heißen ebenfalls komplexe Elemente und werden so definiert:
Das vorangegangene Beispiel zeigt eine gültige XSD für das XML-Dokument in Listing 43.2. In Zeile 006 bis Zeile 014 wird das gruss-Kindelement deklariert. Das Element soll Inhalte vom Typ String enthalten. Dies können wir aber an dieser Stelle nicht über das type-Attribut am gruss-Element ausdrücken, weil es ein complexType-Element enthält. Mit dem extension-Element leiten wir es stattdessen von einem Element ab, das einen String aufnehmen kann. Außerdem definieren wir ein bundesland-Attribut, das Inhalte vom Typ String aufnehmen kann.
Da XML Schema Definitionen XML-Dokumente sind, kann man natürlich normale XML-Kommentare verwenden. In XSDs gibt es einen weiteren Weg, der es im Gegensatz zu den normalen XML-Kommentaren ermöglicht, Kommentare maschinell zu verarbeiten, denn es handelt sich um normale Elemente. Das ist beispielsweise praktisch, um aus einer XML Schema Definiton eine Dokumentation zu generieren:
001 <?xml version="1.0" encoding="iso-8859-15"?> 002 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 003 <xs:element name="gruesse"> 004 <xs:annotation> 005 <xs:documentation xml:lang="DE"> 006 Grüße in verschiedenen Bundesländern 007 </xs:documentation> 008 </xs:annotation> 009 ... 010 </xs:element> 011 </xs:schema> |
Wie bei einer DTD muss auch ein XSD-validierbares XML-Dokument den Zusammenhang zu seiner Grammatik selbst herstellen. Das XML-Dokument referenziert dazu seine XSD im Wurzelelement. Im folgenden Beispiel wird die XSD so eingebunden, dass man den Elementen keinen Namesraum-Präfix voranstellen muss:
001 <?xml version="1.0" encoding="UTF-8"?> 002 <gruesse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 003 xsi:noNamespaceSchemaLocation="gruesse.xsd"> 004 ... |
Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 7. Auflage, Addison Wesley, Version 7.0 |
<< | < | > | >> | API | © 1998, 2011 Guido Krüger & Heiko Hansen, http://www.javabuch.de |