• +49-(0)721-402485-12
Ihre Experten für XML, XQuery und XML-Datenbanken

Einstieg in XML

Nachdem wir nun die Einführung hinter uns haben, wollen wir loslegen. Bevor wir aber geradewegs in Java einsteigen können, müssen wir einige grundlegende Strukturen klären. Es geht besonders um ein allgemeines Verständnis der Konzepte von XML und darum, wie diese Sprache funktioniert. Mit anderen Worten: Sie brauchen einen XML-Einstieg. Wenn Sie bereits XML-Experte sind, dann sollten Sie einfach dieses Kapitel überfliegen, um sicherzugehen, daß Sie mit den besprochenen Themen zurechtkommen. Wenn XML dagegen etwas ganz Neues für Sie ist, dann macht dieses Kapitel Sie fit für den Rest des Buches, ohne Stunden, Tage oder Wochen des Lernens.

Sie können das vorliegende Kapitel auch als Glossar verwenden, wenn Sie den Rest des Buches lesen. Ich werde die Zeit in zukünftigen Kapiteln nicht weiter damit verbringen, XML-Konzepte zu erläutern, damit ich mich ganz auf Java konzentrieren und einige fortgeschrittene Konzepte behandeln kann. Wenn Sie also auf etwas stoßen, daß Sie völlig verwirrt, können Sie in diesem Kapitel nach Information suchen. Und wenn Sie sich dann noch immer ein wenig verloren fühlen, dann empfehle ich Ihnen wärmstens, dieses Buch zusammen mit einem bereitliegenden Exemplar des hervorragenden Buches XML in a Nutshell (O’Reilly) von Elliotte Harold und Scott Means zu lesen. Es wird Ihnen alle Informationen geben, die Sie über die Konzepte von XML benötigen, so daß ich mich auf diejenigen von Java konzentrieren kann.

Darüber hinaus bin ich ein großer Freund von Beispielen. Ich werde die restlichen Kapitel so voll damit packen, wie es nur geht. Es ist mir wichtiger, Ihnen genug Informationen zu geben, als Sie zu unterhalten. Um bereits jetzt damit anzufangen, führe ich in diesem Kapitel einige Dokumente ein, sowohl XML-Dokumente als auch andere, die damit zu tun haben, um die Konzepte in diesem Einstieg zu veranschaulichen. Sie sollten sich die Zeit nehmen, diese in Ihren Editor einzutippen oder sie von der Website zum Buch (http://www.newInstance.com) herunterzuladen, denn sie werden in diesem Kapitel und im gesamten restlichen Buch verwendet. Dies wird Ihnen später Zeit ersparen.

Die Grundlagen

Alles beginnt mit der XML 1.0-Empfehlung, die Sie vollständig unter http://www.w3.org/TR/REC-xml nachlesen können. Beispiel 2-1 zeigt ein einfaches XML-Dokument, das dieser Spezifikation genügt. Es ist ein Auszug des in XML geschriebenen Inhaltsverzeichnisses dieses Buches (ich habe nur einen Teil davon aufgeführt, weil es sehr lang ist!). Die vollständige Datei ist in den (englischsprachigen) Beispieldateien für das Buch enthalten, die unter http://www.oreilly.com/catalog/javaxml2 bzw. http://www.oreilly.de/catalog/javaxml2ger und http://www.newInstance.com verfügbar sind. Ich verwende dieses Dokument, um mehrere wichtige Konzepte zu veranschaulichen.

Beispiel 2-1: Das Dokument contents.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE buch SYSTEM "DTD/JavaXML.dtd">

<!-- Java und XML Inhalt -->
<buch xmlns="http://www.oreilly.com/javaxml2"
      xmlns:ora="http://www.oreilly.com"
>
  <titel ora:serie="Java">Java und XML</titel>

  <!-- Kapitelliste -->
  <inhalt>
    <kapitel titel="Einleitung" nummer="1">
      <thema name="XML spielt eine wichtige Rolle" />
      <thema name="Was ist wichtig?" />
      <thema name="Was Sie benötigen" />
      <thema name="Und was kommt jetzt?" />
    </kapitel>
    <kapitel titel="Ans Eingemachte" nummer="2">
      <thema name="Die Grundlagen" />
      <thema name="Beschränkungen" />
      <thema name="Transformationen" />
      <thema name="Und mehr..." />
      <thema name="Und was kommt jetzt?" />
    </kapitel>
    <kapitel titel="SAX" nummer="3">
      <thema name="Vorbereitungen" />
      <thema name="SAX-Reader" />
      <thema name="Content-Handler" />
      <thema name="Vorsicht Falle!" />
      <thema name="Und was kommt jetzt?" />
    </kapitel> 
    <kapitel titel="Fortgeschrittenes SAX" nummer="4">
      <thema name="Eigenschaften und Features" />
      <thema name="Weitere Handler" />
      <thema name="Filter und Writer" />
      <thema name="Und noch mehr Handler" />
      <thema name="Vorsicht Falle!" />
      <thema name="Und was kommt jetzt?" />
    </kapitel>
    <kapitel titel="DOM" nummer="5">
      <thema name="Das Document Object Model" />
      <thema name="Serialisierung" />
      <thema name="Wandelbarkeit" />
      <thema name="Vorsicht Falle!" />
      <thema name="Und was kommt jetzt?" />
    </kapitel>           

    <!-- Und so weiter... -->

  </inhalt>

  <ora:copyright>&OReillyCopyright;</ora:copyright>
</buch>

XML 1.0

Vieles in dieser Spezifikation beschreibt Dinge, die so gut wie intuitiv sind. Wenn Sie je HTML- oder SGML-Dokumente verfaßt haben, sind Sie bereits mit dem Konzept der Elemente (wie inhalt und kapitel im Beispiel) und Attribute (wie titel und name) vertraut. XML ist nicht viel mehr als die Definition, wie diese Dinge verwendet werden und wie ein Dokument strukturiert werden muß. XML verwendet mehr Zeit darauf, knifflige Probleme wie die Verwendung von Leerzeichen zu definieren als irgendwelche Konzepte, mit denen Sie nicht schon zumindest halbwegs vertraut sind.

Ein XML-Dokument läßt sich in zwei grundlegende Bestandteile aufteilen: den Header, der einem XML-Parser und XML-Anwendungen Informationen darüber gibt, wie dieses Dokument behandelt werden muß, und in den Inhalt, also in die XML-Daten als solche. Obwohl dies eine ziemlich lockere Unterteilung ist, hilft sie uns, die Informationen für Anwendungen innerhalb eines XML-Dokuments vom eigentlichen XML-Inhalt zu unterscheiden, und es ist wichtig, diesen Unterschied zu verstehen. Der Header ist einfach die XML-Deklaration, in diesem Format:

<?xml version="1.0"?>

Der Header kann auch Angaben über die Zeichencodierung enthalten und darüber, ob das Dokument ein Standalone-Dokument ist oder ob ein Bezug zu anderen Dokumenten hergestellt werden muß, um seine Bedeutung vollständig zu verstehen.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

Der Rest des Headers besteht aus Punkten wie der DOCTYPE-Deklaration:

<!DOCTYPE buch SYSTEM "DTD/JavaXML.dtd">

In diesem Fall beziehe ich mich auf eine Datei namens JavaXML.dtd im Verzeichnis DTD/ meines lokalen Dateisystems. Immer, wenn Sie einen absoluten oder relativen Dateipfad oder eine URL verwenden, sollten Sie das Schlüsselwort SYSTEM benutzen. Die andere Möglichkeit besteht darin, das Schlüsselwort PUBLIC zu verwenden und anschließend einen Public-Identifier anzugeben. Das bedeutet, daß das W3C oder ein anderes Konsortium eine Standard-DTD definiert hat, die mit diesem Public-Identifier verknüpft ist. Als Beispiel finden Sie hier die DTD-Deklaration für XHTML 1.0:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Hier wird ein Public-Identifier angegeben (der lustige kleine String, der mit »-//« anfängt), gefolgt von einem System-Identifier (der URL).

Sie können oben in der Datei auch oft Steueranweisungen finden. Diese werden im Allgemeinen als Teil des Dokument-Headers und nicht als Teil seines Inhalts betrachtet. Sie sehen folgendermaßen aus:

<?xml-stylesheet href="XSL\JavaXML.html.xsl" type="text/xsl"?>
<?xml-stylesheet href="XSL\JavaXML.wml.xsl" type="text/xsl" 
                 media="wap"?>
<?cocoon-process type="xslt"?>

Jede solche Anweisung sollte ein Ziel (das erste Wort, wie etwa xml-stylesheet oder cocoon-process) und Daten (den Rest) beinhalten. Häufig, aber nicht immer, werden die Daten in Form von Name-Wert-Paaren hingeschrieben, was tatsächlich die Lesbarkeit verbessern kann. Dies ist aber nur eine gute Angewohnheit, keine Notwendigkeit, also verlassen Sie sich nicht darauf.

Der gesamte restliche Teil Ihres XML-Dokuments sollte aus Inhalt bestehen; mit anderen Worten: aus Elementen, Attributen und Daten, die Sie hineingeschrieben haben.

Das Wurzelelement

Das Wurzelelement ist das in der Hierarchie am höchsten stehende Element im XML-Dokument, und es muß das zuerst geöffnete und zuletzt geschlossene Tag im Dokument sein. Es bietet einen Bezugspunkt, damit ein XML-Parser oder eine XML verwendende Anwendung den Beginn und das Ende eines XML-Dokuments erkennen kann. In unserem Beispiel ist buch das Wurzelelement:

<buch xmlns="http://www.oreilly.com/javaxml2"
      xmlns:ora="http://www.oreilly.com"
>
    <!-- Dokumentinhalt -->
</buch>

Dieses Tag und das zugehörige schließende Tag umschließen alle anderen Daten, die im XML-Dokument enthalten sind. XML legt fest, daß es in einem Dokument nur ein Wurzelelement geben darf. Mit anderen Worten: Das Wurzelelement muß alle anderen Elemente innerhalb des Dokuments einschließen. Abgesehen von dieser Notwendigkeit unterscheidet sich ein Wurzelelement nicht von irgendeinem anderen XML-Element. Es ist wichtig, das zu verstehen, da XML-Dokumente auf andere XML-Dokumente verweisen oder sie enthalten können. In diesen Fällen wird das Wurzelelement des verknüpften Dokuments zu einem eingeschlossenen Element im enthaltenden Dokument und muß durch einen XML-Parser normal behandelt werden. Die Definition von Wurzelelementen als gewöhnliche XML-Elemente ohne besondere Eigenschaften oder Verhaltensweisen führt dazu, daß das Einschließen von Dokumenten reibungslos funktioniert.

Elemente

Bis jetzt habe ich die eigentliche Definition eines Elements unterschlagen. Nun wollen wir uns Elemente näher anschauen; sie können willkürlich gewählte Namen haben und müssen von spitzen Klammern umschlossen werden. Es gibt im Beispieldokument verschiedene Varianten von Elementen, wie Sie hier sehen können:

 <!-- Standardelement, öffnendes Tag -->
 <inhalt>

  <!-- Standardelement mit Attribut -->
  <kapitel titel="Ans Eingemachte" nummer="2">

  <!-- Element mit Textdaten -->
  <titel ora:serie="Java">Java und XML</titel>

  <!-- Leeres Element -->
  <abschnittsBegrenzung />

 <!-- Standardelement, schließendes Tag -->
 </inhalt>

Die erste Regel beim Erstellen von Elementen lautet, daß ihre Namen mit einem Buchstaben oder Unterstrich beginnen müssen und daß sie dann beliebig viele Buchstaben, Ziffern, Unterstriche, Bindestriche oder Punkte enthalten dürfen. Elementnamen dürfen keine eingebetteten Leerzeichen enthalten:

<!-- Eingebettete Leerzeichen sind nicht erlaubt -->
<mein kleines element>

XML unterscheidet bei Elementnamen im übrigen zwischen Groß- und Kleinschreibung. Im Allgemeinen wird die Verwendung der gleichen Regeln, die auch für Java-Variablennamen gelten, zu einer sauberen XML-Elementbenennung führen. Die Verwendung eines Elements namens tkuo zur Darstellung von Telekommunikationsunternehmensobjekt ist keine gute Idee, weil diese Bezeichnung kryptisch ist, wogegen ein ausufernder Tagname wie beginnEinesNeuenKapitels ein Dokument übermäßig vollgestopft erscheinen läßt. Denken Sie daran, daß Ihre XML-Dokumente wahrscheinlich auch von anderen Entwicklern und Inhaltsautoren gelesen werden, insofern ist eine klare Dokumentation durch gute Namenswahl ein Grundbedürfnis.

Jedes geöffnete Element muß auch wieder geschlossen werden. Es gibt keine Ausnahmen von dieser Regel wie in vielen anderen Auszeichnungssprachen, etwa in HTML. Ein schließendes Element besteht aus einem Slash mit dem Elementnamen dahinter: </inhalt>. Zwischen einem öffnenden und einem schließenden Tag können beliebig viele weitere Elemente oder Textdaten stehen. Sie dürfen allerdings nicht die Reihenfolge verschachtelter Tags durcheinanderbringen: Das zuerst geöffnete Element muß immer als letztes geschlossen werden. Wenn irgendeiner Regel der XML-Syntax in einem XML-Dokument nicht Folge geleistet wird, dann ist das Dokument nicht wohlgeformt.

Ein wohlgeformtes Dokument ist eines, in dem allen XML-Syntaxregeln Folge geleistet wird und in dem alle Elemente und Attribute korrekt positioniert sind. Ein wohlgeformtes Dokument ist allerdings nicht notwendigerweise gültig, was nämlich bedeutet, daß es sich an die Beschränkungen hält, die einem Dokument durch seine DTD oder sein Schema auferlegt werden. Es gibt einen bedeutenden Unterschied zwischen einem wohlgeformten und einem gültigen Dokument; die Regeln, die ich in diesem Abschnitt bespreche, sorgen dafür, daß Ihr Dokument wohlgeformt ist, während die Regeln, die im Abschnitt über Beschränkungen besprochen werden, es ermöglichen, daß Ihr Dokument gültig ist.

Als Beispiel für ein Dokument, das nicht wohlgeformt ist, schauen Sie sich dieses XML-Fragment an:

<tag1>
 <tag2>
</tag1>
 </tag2>

Die Reihenfolge der Verschachtelung der Tags ist nicht korrekt, da dem öffnenden <tag2> innerhalb des umschließenden Elements tag1 kein schließendes </tag2> folgt. Wird dieser Syntaxfehler jedoch verbessert, besteht immer noch keine Garantie dafür, daß das Dokument dadurch gültig wird.

Obwohl dieses Beispiel eines nicht wohlgeformten Dokuments trivial erscheinen mag, sollten Sie daran denken, daß dies akzeptables HTML wäre und häufig in großen Tabellen innerhalb eines HTML-Dokuments zum Einsatz kommt. Mit anderen Worten benötigen HTML und viele andere Auszeichnungssprachen keine wohlgeformten XML-Dokumente. Die strikte Einhaltung der Reihenfolgen- und Verschachtelungsregeln in XML sorgt dafür, daß das Parsing und die Bearbeitung von Daten erheblich schneller vonstatten gehen als bei der Verwendung von Auszeichnungssprachen ohne diese Beschränkungen.

Die letzte Regel, die ich erläutere, betrifft leere Elemente. Ich sagte bereits, daß XML-Tags immer paarweise auftreten müssen; ein öffnendes und ein schließendes Tag bilden zusammen ein vollständiges XML-Element. Es gibt Fälle, in denen ein Element ganz allein verwendet wird, z.B. als Flag, das anzeigt, daß ein Kapitel unvollständig ist, oder als Element, das Attribute, aber keine Textdaten hat, wie eine Bildeinbettung in HTML. Dies müßte so dargestellt werden:

<kapitelUnvollstaendig></kapitelUnvollstaendig>
<img src="/images/xml.gif"></img>

Das ist natürlich ein bißchen blöd und bläht XML-Dokumente unnötig auf, die vielleicht ohnehin schon sehr umfangreich sind. Die XML-Spezifikation stellt ein Mittel zur Verfügung, um sowohl ein öffnendes als auch ein schließendes Tag in einem einzigen Element anzuzeigen:

<kapitelUnvollstaendig />
<img src="/images/xml.gif" />

Attribute

Zusätzlich zu dem Text, der zwischen den Tags eines Elements enthalten ist, kann ein Element Attribute besitzen. Attribute sind mit ihren zugehörigen Werten in der öffnenden Deklaration des Elements enthalten (die auch seine schließende Deklaration sein kann!). Zum Beispiel handelt es sich beim Titel eines Kapitels im Tag kapitel um eine Information, die in einem Attribut notiert wurde:

<kapitel titel="Fortgeschrittenes SAX" nummer="4">
  <thema name="Eigenschaften und Features" />
  <thema name="Weitere Handler" />
  <thema name="Filter und Writer" />
  <thema name="Und noch mehr Handler" />
  <thema name="Vorsicht Falle!" />
  <thema name="Und was kommt jetzt?" />
</kapitel>

In diesem Beispiel ist titel der Attributname, der Wert ist der Titel des Kapitels, »Fortgeschrittenes SAX«. Attributnamen müssen denselben Regeln genügen wie XML-Elementnamen, und Attributwerte müssen in Anführungszeichen stehen. Zwar sind sowohl einfache als auch doppelte Anführungszeichen gestattet, aber doppelte Anführungszeichen sind ein weitverbreiteter Standard und ergeben XML-Dokumente, die der Java-Programmierpraxis nachempfunden sind. Abgesehen davon könnte es sein, daß Attributwerte selbst einfache oder doppelte Anführungszeichen enthalten; das Einschließen der Werte in doppelte Anführungszeichen ermöglicht die Verwendung einfacher Anführungszeichen als Teil des Wertes, und das Einschließen in einfache Anführungszeichen macht die Verwendung doppelter Anführungszeichen innerhalb des Wertes möglich. Allerdings ist dies nicht sehr empfehlenswert, da XML-Parser und -Prozessoren oftmals alle Anführungszeichen um einen Attributwert herum gleichförmig in doppelte (oder in einzelne) Anführungszeichen umwandeln, was möglicherweise zu unerwarteten Ergebnissen führen könnte.

Abgesehen davon, daß Sie lernen müssen, wie Attribute verwendet werden, müssen Sie auch wissen, wann sie verwendet werden. Da XML einen solchen Variationsreichtum bei der Formatierung von Daten zuläßt, kommt es selten vor, daß ein Attribut nicht durch ein Element dargestellt werden kann, oder daß ein Element nicht einfach in ein Attribut konvertiert werden kann. Obwohl es keine Spezifikation und keinen weitgehend akzeptierten Standard für die Entscheidung gibt, wann ein Attribut und wann ein Element verwendet werden sollte, gibt es doch eine gute Faustregel: Verwenden Sie Elemente für Daten mit mehreren Werten und Attribute für Daten mit nur einem Wert.

Wenn Daten mehrere Werte haben können oder sehr umfangreich sind, dann gehören sie am ehesten in ein Element. Dieses kann vorzugsweise als Textdaten behandelt werden und ist dadurch einfach zu durchsuchen und zu verwenden. Beispiele wären die Beschreibung der Kapitel eines Buches oder URLs, die die Details zu verwandten Links einer Site enthalten. Werden die Daten jedoch primär als einzelner Wert dargestellt, dann lassen sie sich am besten durch ein Attribut darstellen. Ein guter Kandidat für ein Attribut ist die Information, zu welchem Teil des Buches ein Kapitel gehört; während dieser Buchteil selbst ein Element wäre und seinen eigenen Titel haben könnte, könnte die Gruppierung der Kapitel zu einem Buchteil einfach durch ein Attribut namens buchteil innerhalb des Elements kapitel dargestellt werden. Dieses Attribut würde ein einfaches Gruppieren und Indizieren von Kapiteln ermöglichen, aber es würde dem Anwender niemals direkt angezeigt werden.

Ein weiteres gutes Beispiel für Daten, die sich in XML als Attribut darstellen lassen, ist die Information, ob ein bestimmter Tisch oder Stuhl auf Lager vorrätig ist. Daraus könnte sich für eine XML-Anwendung, die für die Erstellung einer Broschüre oder eines Flyers verwendet wird, die Anweisung ableiten, keine Artikel aufzunehmen, die sich nicht im aktuellen Lagerbestand befinden; offensichtlich handelt es sich dabei um einen Wahr-oder-Falsch-Wert, der zu einem bestimmten Zeitpunkt nur einen bestimmten Wert hat. Wieder würde der Anwendungsclient diese Information niemals direkt zu Gesicht bekommen, aber die Daten würden verwendet, um das XML-Dokument zu behandeln und zu bearbeiten. Wenn Sie sich nach dieser ganzen Analyse noch unsicher sind, können Sie immer auf Nummer sicher gehen und ein Element verwenden.

Möglicherweise sind Ihnen bereits alternative Möglichkeiten eingefallen, um diese verschiedenen Beispiele darzustellen. Beispielsweise könnte es sinnvoll sein, titel-Elemente in ein Element kapitel hineinzuverschachteln, anstatt ein Attribut titel zu verwenden. Vielleicht könnte ein leeres Tag <lager /> nützlich sein, um Möbel zu kennzeichnen, die sich auf Lager befinden. In XML gibt es selten nur eine Möglichkeit, die Darstellung von Daten vorzunehmen, und oft gibt es mehrere gute Optionen, um die gleiche Aufgabe zu erfüllen. In den meisten Fällen bestimmen die Anwendung und die Datenverwendung, was am sinnvollsten ist. Anstatt Ihnen zu sagen, wie XML-Dokumente geschrieben werden, was schwierig wäre, zeige ich Ihnen, wie XML verwendet wird, so daß Sie einen Einblick bekommen, wie unterschiedlich Datenformate bearbeitet und verwendet werden können. Dies gibt Ihnen das nötige Wissen an die Hand, um Ihre eigenen Entscheidungen darüber zu treffen, wie Sie Ihre XML-Dokumente formatieren möchten.

Entity-Referenzen und Konstanten

Ein Thema, das ich bisher noch nicht behandelt habe, sind Escape-Sequenzen oder der Bezug auf andere konstantenartige Werte. Zum Beispiel besteht die übliche Art, den Pfad zu einem Installationsverzeichnis darzustellen, darin, etwas wie <Verzeichnis-von-Cocoon> zu schreiben. Hier ersetzt der Anwender den Text durch das entsprechend ausgewählte Installationsverzeichnis. In diesem Beispiel soll das Kapitel, in dem Web-Anwendungen besprochen werden, Details über die Installation und Anwendung von Apache Cocoon zur Verfügung stellen, und diese Daten sollen als Inhalt eines Elements dargestellt werden:

<thema>
 <ueberschrift>Installing Cocoon</ueberschrift>
 <inhalt>
  Machen Sie die Datei Cocoon.properties im Verzeichnis
  <Verzeichnis-von-Cocoon>/bin ausfindig.
 </inhalt>
</thema>

Das Problem besteht darin, daß XML-Parser versuchen, diese Daten als XML-Tag zu behandeln und dann einen Fehler erzeugen, weil es kein schließendes Tag gibt. Dies ist ein gängiges Problem, da jede Verwendung spitzer Klammern dieses Verhalten zur Folge hat. Entity-Referenzen stellen eine Möglichkeit zur Verfügung, dieses Problem zu umgehen. Eine Entity-Referenz ist ein besonderer Datentyp in XML, der verwendet wird, um auf andere Daten Bezug zu nehmen. Die Entity-Referenz besteht aus einem eindeutigen Namen mit vorangestelltem Und-Zeichen und nachgestelltem Semikolon: &[entity-name];. Wenn ein XML-Parser auf eine Entity-Referenz stößt, wird der festgelegte Ersatzwert eingesetzt und nicht weiter bearbeitet. XML definiert fünf Entities, um das im Beispiel angesprochene Problem zu lösen: &lt; für das Kleiner-Zeichen, &gt; für das Größer-Zeichen, &amp; für das Und-Zeichen (Ampersand) selbst, &quot; für ein doppeltes Anführungszeichen und &apos; für ein einfaches Anführungszeichen. Durch die Verwendung dieser speziellen Verweise können Sie den Bezug auf das Installationsverzeichnis folgendermaßen korrekt angeben:

<thema>
 <ueberschrift>Installing Cocoon</ueberschrift>
 <inhalt>
  Machen Sie die Datei Cocoon.properties im Verzeichnis
  &lt;Verzeichnis-von-Cocoon&gt;/bin ausfindig.
 </inhalt>
</thema>

Wenn dieses Dokument vom Parser bearbeitet wird, werden diese Daten als »<Verzeichnis-von-Cocoon>« interpretiert, und das Dokument gilt noch immer als wohlgeformt.

Beachten Sie, daß Entity-Referenzen auch benutzerdefiniert sein können. Dies ermöglicht eine Art abkürzende Schreibweise; in dem XML-Beispiel, das ich gerade durchgehe, beziehe ich den Copyright-Text aus einer externen gemeinsamen Datei. Da dieses Copyright für mehrere O’Reilly-Bücher verwendet wird, möchte ich den eigentlichen Text nicht in das XML-Dokument einschließen; wird jedoch das Copyright geändert, dann sollte das XML-Dokument diese Änderung mitmachen. Sie können feststellen, daß die Syntax, die im XML-Dokument verwendet wird, genauso aussieht wie die vordefinierten XML-Entity-Referenzen:

<ora:copyright>&OReillyCopyright;</ora:copyright>

Obwohl Sie bis zum Abschnitt über DTDs nicht erfahren werden, wie dem XML-Parser mitgeteilt wird, was er darstellen soll, wenn er auf &OReillyCopyright; trifft, können Sie schon hier sehen, daß es mehr Verwendungsmöglichkeiten für Entity-Referenzen gibt als nur die Darstellung schwieriger oder ungebräuchlicher Zeichen innerhalb der Daten.

Daten vor dem Parser bewahren

Das letzte XML-Konstrukt, das wir betrachten, ist die Abschnittsmarkierung CDATA. Ein CDATA-Abschnitt wird verwendet, wenn eine größere Menge Daten ohne Bearbeitung durch den XML-Parser an die anfordernde Anwendung weitergereicht werden soll. Davon wird Gebrauch gemacht, wenn eine ungewöhnlich große Anzahl von Zeichen durch Entity-Referenzen umschrieben werden müßten oder wenn Abstände durch Leerzeichen erhalten bleiben müssen. In einem XML-Dokument sieht ein CDATA-Abschnitt folgendermaßen aus:

<nicht-parser-daten>
  <![CDATA[Diagramm:
       <Schritt 1>Installieren Sie Cocoon nach "/usr/lib/cocoon"
       <Schritt 2>Machen Sie die richtige Konfigurationsdatei ausfindig.
       <Schritt 3>Laden Sie Ant von "http://jakarta.apache.org" herunter
                                    -----> Verwenden Sie CVS dafür <----
  ]]>
</nicht-parser-daten>

In diesem Beispiel benötigt die Information innerhalb des CDATA-Abschnitts keine Entity-Referenzen oder anderen Mechanismen, um den Parser zu warnen, daß reservierte Zeichen verwendet werden; statt dessen gibt der XML-Parser sie unverändert an das umgebende Programm oder die Anwendung weiter.

An diesem Punkt haben Sie die Hauptbestandteile von XML-Dokumenten kennengelernt. Obwohl jeder von ihnen nur recht knapp beschrieben wurde, sollte Ihnen dies genügend Informationen geben, um XML-Tags zu erkennen, wenn Sie sie sehen, und um ihren allgemeinen Verwendungszweck zu kennen. Mit bestehenden Ressourcen wie O’Reillys XML in a Nutshell an Ihrer Seite sind Sie nun in der Lage, sich einige fortgeschrittenere XML-Spezifikationen anzuschauen.

Namensräume

Auch wenn ich hier nicht allzutief auf das Thema XML-Namensräume eingehen möchte, sollten Sie sich die Verwendung eines Namensraumes im Wurzelelement von Beispiel 2-1 ansehen. Ein XML-Namensraum ist ein Mittel, um ein oder mehrere Elemente in einem XML-Dokument mit einer bestimmten URI zu verknüpfen. Das bedeutet konkret, daß das Element sowohl durch seinen Namen als auch durch seine Namensraum-URI identifiziert wird. In unserem XML-Beispiel könnte es später nötig sein, Teile von anderen O’Reilly-Büchern einzufügen. Da jedes dieser Bücher ebenfalls die Elemente kapitel, ueberschrift oder thema enthalten kann, muß das Dokument so gestaltet und aufgebaut werden, daß das Problem einer Kollision mit den Namensräumen anderer Dokumente vermieden wird.

Die XML-Namensraumspezifikation löst dieses Problem auf angenehme Weise. Da das XML-Dokument ein bestimmtes Buch darstellt und kein anderes XML-Dokument dasselbe Buch darstellen sollte, kann die Verwendung eines Namensraumes, der mit einer URI wie http://www.oreilly.com/javaxml2 verknüpft ist, einen eindeutigen Namensraum erzeugen. Die Namensraumspezifikation fordert, daß eine eindeutige URI einem Präfix zugeordnet wird, um die Elemente im einen Namensraum von denjenigen in anderen Namensräumen zu unterscheiden. Es wird empfohlen, eine URL zu verwenden, die wie folgt angegeben wird:

<buch xmlns="http://www.oreilly.com/javaxml2"
      xmlns:ora="http://www.oreilly.com"
>

Tatsächlich habe ich zwei Namensräume definiert. Der erste wird als Standard-Namensraum betrachtet, da kein Präfix angegeben wurde. Jedes Element ohne Präfix wird mit diesem Namensraum in Verbindung gebracht. Letzten Endes gehören alle Elemente im XML-Dokument, außer dem Element copyright mit dem Präfix ora, zu diesem Standard-Namensraum. Der zweite Namensraum definiert ein Präfix, was dazu führt, daß das Tag <ora:copyright> mit diesem zweiten Namensraum in Verbindung gebracht wird.

Ein letzter interessanter (und etwas verwirrender) Punkt: XML Schema, worüber ich in einem späteren Abschnitt mehr sagen werde, setzt voraus, daß das Schema eines XML-Dokuments auf eine Art und Weise angegeben wird, die dem Einstellen der Namensraum-Deklaration sehr ähnlich sieht; siehe Beispiel 2-2.

Beispiel 2-2: Auf ein XML Schema zugreifen

<?xml version="1.0"?>
<addreßBuch xmlns:xsi="http://www.w3.org/1999/XMLSchema/instance"
             xmlns="http://www.oreilly.com/catalog/javaxml"
             xsi:schemaLocation="http://www.oreilly.com/catalog/javaxml
                                 mySchema.xsd"
>
  <person>
    <name>
      <vorname>Brett</vorname>
      <nachname>McLaughlin</nachname>
    </name>
    <email>brettmclaughlin@earthlink.net</email>
  </person>
  <person>
    <name>
      <vorname>Eddie</vorname>
      <nachname>Balucci</nachname>
    </name>
    <email>eddieb@freeworld.net</email>
  </person>
</addreßBuch>

Hier passieren verschiedene Dinge, und es ist wichtig, sie alle zu verstehen. Als erstes wird der Namensraum der XML Schema-Instanz definiert und mit einer URL assoziiert. Dieser Namensraum, abgekürzt xsi, wird verwendet, um in XML-Dokumenten Informationen über ein Schema anzugeben, genau wie es hier zu sehen ist. Auf diese Weise sorgt die erste Zeile dafür, daß die Elemente der XML Schema-Instanz dem Dokument zur Verfügung stehen. Die nächste Zeile definiert den Namensraum für das XML-Dokument selbst. Da das Dokument keinen expliziten Namensraum verwendet, wie denjenigen, der in früheren Beispielen mit http://www.oreilly.com/javaxml2 verknüpft wurde, wird nur der Standard-Namensraum deklariert. Das bedeutet, daß alle Elemente ohne expliziten Namensraum und zugewiesenes Präfix (in diesem Beispiel also alle) mit diesem Standard-Namensraum verknüpft werden.

Werden sowohl der Namensraum des Dokuments als auch der Namensraum des XML Schemas auf diese Weise definiert, können wir unser Vorhaben in die Tat umsetzen, nämlich ein Schema mit diesem Dokument verknüpfen. Das Attribut schemaLocation, das zum Namensraum der XML Schema-Instanz gehört, wird verwendet, um dies zu erreichen. Ich habe diesem Attribut seinen Namensraum vorangestellt (xsi), der gerade definiert wurde. Das Argument dieses Attributs sind in Wirklichkeit zwei URIs: die erste gibt den Namensraum an, der mit einem Schema verknüpft ist, und der zweite die URI des Schemas, auf das Bezug genommen wird. In diesem Beispiel führt das dazu, daß die erste URI der Standard-Namensraum ist, der einfach nur deklariert wird, und die zweite eine Datei im lokalen Dateisystem namens mySchema.xsd. Wie jedes andere XML-Attribut wird das vollständige Paar in einen einzelnen Satz von Anführungszeichen eingeschlossen. Und so einfach haben Sie in Ihrem Dokument auf ein Schema zugegriffen!

Ganz im Ernst: Es ist nicht so einfach, und es ist einer der am häufigsten mißverstandenen Punkte bei der Verwendung von Namensräumen und XML Schema. Ich werde die hier verwendete Vorgehensweise später näher beleuchten. Merken Sie sich im Moment einfach, wie Namensräume die Verwendung von Elementen aus verschiedenen Gruppen ermöglichen, die dennoch als Teile ihrer speziellen Gruppen identifizierbar bleiben.

Beschränkungen

Als nächstes ist der Umgang mit der Beschränkung von XML an der Reihe. Wenn Sie aus diesem Kapitel sonst nichts mitnehmen, aber den Sinn der Beschränkungen von XML verstehen, dann bin ich ein glücklicher Autor. Da XML erweiterbar ist und Daten auf Hunderte oder sogar Tausende von Arten darstellen kann, verleihen Beschränkungen eines Dokuments diesen unterschiedlichen Formaten eine Bedeutung. Ohne Dokumentbeschränkungen ist es (in den meisten Fällen) unmöglich herauszubekommen, was die Daten in einem Dokument bedeuten. In diesem Abschnitt werde ich die beiden aktuellen Standardmittel zur Beschränkung von XML besprechen: DTDs (Bestandteil der XML-1.0-Spezifikation) und XML Schema (vor kurzem vom W3C als Standard herausgegeben). Wählen Sie einfach das Mittel, das am besten paßt.

DTDs

Ein XML-Dokument ist nicht sehr nützlich ohne eine begleitende DTD (oder ein Schema). Genau wie XML effektiv Daten beschreiben kann, macht die DTD die Daten für viele verschiedene Programme auf unterschiedliche Weise nutzbar, indem sie die Struktur der Daten definiert. In diesem Abschnitt zeige ich Ihnen die gebräuchlichsten Konstrukte, die innerhalb einer DTD verwendet werden. Ich verwende wieder die XML-Darstellung eines Teils des Inhaltsverzeichnisses für dieses Buch als Beispiel und gehe den Konstruktionsprozeß einer DTD für das XML-Inhaltsverzeichnis-Dokument durch.

Die DTD definiert, wie Daten formatiert werden. Sie muß folgende Bestandteile eines XML-Dokuments definieren: jedes erlaubte Element, die erlaubten Attribute und möglicherweise auch die akzeptierten Attributwerte für jedes Element, die Verschachtelung und Auftrittsfolge jedes Elements sowie alle externen Entities. DTDs können noch viele andere Aspekte eines XML-Dokuments angeben, aber auf diese Grundlagen werden wir uns konzentrieren. Sie lernen die Konstrukte, die eine DTD zu bieten hat, kennen, indem Sie sie auf die XML-Datei aus Beispiel 2-1 anwenden und diese damit beschränken. Die vollständige DTD, auf die ich mich in diesem Beispiel beziehe, wird in Beispiel 2-3 gezeigt.

Beispiel 2-3: DTD für Beispiel 2-1

<!ELEMENT buch (titel, inhalt, ora:copyright)>
<!ATTLIST buch
          xmlns       CDATA  #REQUIRED
          xmlns:ora   CDATA  #REQUIRED
>
<!ELEMENT titel (#PCDATA)>
<!ATTLIST titel
          ora:serie   (C | Java | Linux | Oracle | 
                      Perl | Web | Windows)   
                      #REQUIRED
>
<!ELEMENT inhalt (kapitel+)>
<!ELEMENT kapitel (thema+)>
<!ATTLIST kapitel
          titel       CDATA  #REQUIRED
          nummer      CDATA  #REQUIRED
>
<!ELEMENT thema EMPTY>
<!ATTLIST thema
          name        CDATA  #REQUIRED
>

<!-- Copyright-Information -->
<!ELEMENT ora:copyright (copyright)>
<!ELEMENT copyright (jahr, inhalt)>
<!ATTLIST copyright
          xmlns  CDATA  #REQUIRED
>
<!ELEMENT jahr EMPTY>
<!ATTLIST jahr
          wert   CDATA  #REQUIRED
>
<!ELEMENT inhalt (#PCDATA)>
<!ENTITY OReillyCopyright SYSTEM
   "http://www.newInstance.com/javaxml2/copyright.xml"
>

Elemente

Ein Großteil der DTD besteht aus ELEMENT-Definitionen (die in diesem Abschnitt behandelt werden) und ATTRIBUTE-Definitionen (siehe nächsten Abschnitt). Eine Elementdefinition beginnt mit dem Schlüsselwort ELEMENT hinter dem Standardbeginn <! eines DTD-Tags, gefolgt vom Namen des Elements. Hinter diesem Namen befindet sich das Content-Modell des Elements. Das Content-Modell steht grundsätzlich in Klammern und gibt an, welcher Inhalt sich im Element befinden kann. Betrachten Sie das Element buch als Beispiel:

<!ELEMENT buch (titel, inhalt, ora:copyright)>

Dies bedeutet, daß jedes buch-Element die Elemente titel, inhalt und ora:copyright enthalten kann. Die Definitionen dieser Elemente folgen später mit ihren jeweiligen Content-Modellen und so weiter. Sie sollten sich darüber im klaren sein, daß die im Content-Modell angegebene Reihenfolge diejenige ist, in der die Elemente im Dokument auftauchen müssen, und zwar genau einmal, wenn keine Modifier verwendet werden (die ich sofort erläutern werde). Im vorliegenden Fall muß jedes buch-Element ohne Ausnahme die Elemente titel, inhalt und dann ora:copyright enthalten. Wird gegen diese Regeln verstoßen, dann wird das Dokument nicht mehr als gültig betrachtet (auch, wenn es noch immer wohlgeformt sein könnte).

Natürlich müssen Sie in vielen Fällen das mehrfache oder optionale Auftreten eines Elements angeben. Sie können dies mit Hilfe der Wiederholungs-Modifier bewerkstelligen, die in Tabelle 2-1 aufgelistet werden.

Tabelle 2-1: DTD-Wiederholungs-Modifier
OperatorBeschreibung
[Standard]Muß genau einmal vorkommen (1)
?Kann einmal vorkommen oder gar nicht (0..1)
+Muß einmal bis unendlich oft vorkommen (1..N)
*Kann beliebig oft vorkommen, auch gar nicht (0..N)

Betrachten Sie als Beispiel die Definition des Elements inhalt:

<!ELEMENT inhalt (kapitel+)>

Hier muß das Element inhalt mindestens ein kapitel-Element enthalten, aber es kann eine unbegrenzte Anzahl solcher Kapitel geben.

Wenn ein Element Zeichendaten enthält, wird als sein Content-Modell das Schlüsselwort #PCDATA verwendet:

<!ELEMENT titel (#PCDATA)>

Wenn ein Element immer leer sein soll, wird das Schlüsselwort EMPTY verwendet:

<!ELEMENT thema EMPTY>

Attribute

Wenn Sie die Elementdefinition abgeschlossen haben, sollten Sie Attribute definieren. Diese werden durch das Schlüsselwort ATTLIST definiert. Der erste Wert ist der Name des Elements, und danach können Sie mehrere Attribute definieren. Diese Definitionen bestehen aus dem Namen des Attributs, seinem Datentyp und aus der Angabe, ob das Attribut erforderlich oder implizit ist (was im wesentlichen bedeutet, daß es nicht erforderlich ist). Die meisten Attribute mit Textwerten sind einfach vom Typ CDATA, wie Sie hier sehen:

<!ATTLIST kapitel
          titel       CDATA  #REQUIRED
          nummer      CDATA  #REQUIRED
>

Sie können auch eine Menge fester Werte angeben, von denen ein Attribut einen annehmen muß, damit das Dokument als gültig betrachtet wird:

<!ATTLIST titel
          ora:serie   (C | Java | Linux | Oracle | 
                      Perl | Web | Windows)   
                      #REQUIRED
>

Entities

Sie können die Auflösung von Entity-Referenzen in einer DTD festlegen, indem Sie das Schlüsselwort ENTITY verwenden. Das funktioniert ziemlich ähnlich wie die DOCTYPE-Referenz, von der ich vorhin sprach, bei der eine Public-ID oder System-ID angegeben werden kann. In der Beispiel-DTD habe ich eine System-ID, eine URL, angegeben, um die Entity-Referenz OReillyCopyright dorthin aufzulösen:

<!ENTITY OReillyCopyright SYSTEM
   "http://www.newInstance.com/javaxml2/copyright.xml"
>

Das führt dazu, daß die Datei copyright.xml an der angegebenen URL als Wert der O’Reilly-Copyright-Entity-Referenz in das Beispieldokument geladen wird. Sie werden dieses Vorgehen in den nächsten paar Kapitel in Aktion erleben.

Dies ist natürlich kein ausführliches Handbuch über DTDs, aber es sollte Ihnen genügend Basiswissen vermitteln, um zurechtzukommen. Wie ich bereits vorgeschlagen habe, sollten Sie einige zusätzliche Bücher oder andere Quellen über XML als solches zur Verfügung haben (etwa XML in a Nutshell), während Sie dieses Buch durcharbeiten, für den Fall, daß Sie mit etwas konfrontiert werden, über das Sie sich im unklaren sind. Indem ich davon ausgehe, daß Sie dieses Buch vorliegen oder Zugang zu den Online-Spezifikationen von http://www.w3.org haben, kann ich mich schneller in Java-Themen vertiefen.

XML Schema

XML Schema ist ein jüngst verabschiedeter Kandidat für eine Empfehlung vom W3C. Es verbessert DTDs, indem es mehr Datentypangaben und recht viele zusätzliche Konstrukte zur Verfügung stellt als diese; gleichzeitig genügt es selbst einem XML-Format. Ich werde die Behandlung von Schemas hier recht kurz halten, weil sie in Java und XML ein Detail »hinter den Kulissen« sind. In den Kapiteln, in denen Sie mit Schema arbeiten werden (zum Beispiel im Kapitel Content-Syndication), werde ich noch einmal spezielle Punkte ansprechen, auf die Sie achten müssen. Allerdings ist die Spezifikation von XML Schema so umfangreich, daß sie ein ganzes Buch für sich benötigen würde. Beispiel 2-4 zeigt das XML Schema, das Beispiel 2-1 beschränkt.

Beispiel 2-4: XML Schema, das Beispiel 2-1 beschränkt

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           xmlns="http://www.oreilly.com/javaxml2" 
           xmlns:ora="http://www.oreilly.com"
           targetNamespace="http://www.oreilly.com/javaxml2"
           elementFormDefault="qualified"
>
  <xs:import namespace="http://www.oreilly.com" 
             schemaLocation="contents-ora.xsd" />

  <xs:element name="buch">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="titel" />
        <xs:element ref="inhalt" />
        <xs:element ref="ora:copyright" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="titel">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute ref="ora:serie" use="required" />
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name="inhalt">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="kapitel" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="thema" maxOccurs="unbounded">
                <xs:complexType>
                  <xs:attribute name="name" 
                                type="xs:string" 
                                use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
            <xs:attribute name="titel" type="xs:string" use="required"/>
            <xs:attribute name="nummer" type="xs:byte" use="required"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>

Zusätzlich benötigen Sie aus Gründen, die Sie gleich verstehen werden, das Schema aus Beispiel 2-5.

Beispiel 2-5: Zusätzliches XML Schema für Beispiel 2-1

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns="http://www.oreilly.com" 
           xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           targetNamespace="http://www.oreilly.com"
           attributeFormDefault="qualified" 
           elementFormDefault="qualified"
>
  <xs:attribute name="serie" type="xs:string"/>
  <xs:element name="copyright" type="xs:string" />
</xs:schema>

Bevor Sie in die Besonderheiten dieser Schemas einsteigen, sollten Sie sich die verschiedenen Namensraumdeklarationen ansehen, die durchgeführt werden. Als erstes wird der XML Schema-Namensraum selbst mit dem Präfix xs versehen, was die Trennung von XML Schema-Konstrukten von den Elementen und Attributen ermöglicht, die durch das Schema beschränkt werden. Als nächstes wird als Standard-Namensraum der Namensraum der zu beschränkenden Elemente eingestellt; in Beispiel 2-4 ist dies der Java-und-XML-Namensraum und in Beispiel 2-5 der O’Reilly-Namensraum. Ich habe zusätzlich dem targetNamespace-Attribut den gleichen Wert zugewiesen. Dieses Attribut gibt dem Schema den Namensraum der Elemente und Attribute bekannt, die beschränkt werden sollen. Das wird leicht vergessen und kann dann ein gewaltiges Chaos verursachen, also denken Sie daran, dieses Attribut mit aufzunehmen. An dieser Stelle werden Namensräume für die zu beschränkenden Elemente (der Standard-Namensraum) und die verwendeten Konstrukte (der XML Schema-Namensraum) definiert.

Als letztes habe ich die Werte von attributeFormDefault und elementFormDefault als »qualified« angegeben. Dies zeigt an, daß ich für die Elemente und Attribute vollständig qualifizierte Namen verwende, nicht nur lokale Namen. Ich werde damit nicht ins Detail gehen, aber ich empfehle Ihnen dringend, immer qualifizierte Namen zu verwenden. Der Versuch, mehrere Namensräume und unqualifizierte Namen gemeinsam zu verwenden, erzeugt ein Durcheinander, in dem ich nicht gern stecken würde.

Elemente und Attribute

Elemente werden durch das Konstrukt element definiert. Sie definieren Ihre eigenen Datentypen grundsätzlich dadurch, daß Sie in das Element element, das (durch das Attribut name) den Namen des Elements bestimmt, ein complexType-Tag hinein verschachteln. Betrachten Sie diesen Ausschnitt aus Beispiel 2-4:

<xs:element name="buch">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="titel" />
      <xs:element ref="inhalt" />
      <xs:element ref="ora:copyright" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

Hier habe ich angegeben, daß das Element buch einen komplexen Inhalt hat. Es soll drei Elemente enthalten: titel, inhalt und ora:copyright. Durch Verwendung des Konstrukts sequence habe ich sichergestellt, daß sie in der angegebenen Reihenfolge auftauchen müssen; und da keine Modifier verwendet wurden, muß ein Element genau einmal auftauchen. Für jedes dieser anderen Elemente habe ich das Schlüsselwort ref verwendet, um Bezug auf andere Elementdefinitionen zu nehmen. Dies verweist auf die Definitionen dieser Elemente an einer anderen Stelle des Schemas und sorgt dafür, daß alles organisiert und leicht nachvollziehbar bleibt.

Weiter unten in der Datei wird das Element titel definiert:

<xs:element name="titel">
  <xs:complexType>
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute ref="ora:serie" use="required" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:element>

Dieses Element ist in der Tat nichts weiter als ein einfacher XML Schema-string-Datentyp; allerdings habe ich ein Attribut hinzugefügt, so daß ich dennoch einen complexType definieren muß. Da ich auf einen existierenden Datentyp aufbaue, verwende ich die Schlüsselwörter simpleContent und extension (als verschachtelte Elemente), um diesen Typ zu definieren. simpleContent informiert das Schema darüber, daß es sich um einen grundlegenden Datentyp handelt, und extension mit dem base-Wert »xs:string« setzt das Schema darüber in Kenntnis, daß ich genau das gestatten möchte, was der XML Schema-Datentyp string gestattet, außer daß hier noch das zusätzliche (mit dem Schlüsselwort attribute definierte) Attribut hinzukommt. Was das Attribut selbst angeht, beziehe ich mich auf den woanders definierten Datentyp und gebe (durch use="required") an, daß es in diesem Element auftauchen muß. Ich merke gerade, daß dieser Absatz ein ganz schöner Brocken und auch nicht ganz einfach verständlich ist; aber wenn Sie sich ein wenig Zeit nehmen, werden Sie alles begreifen.

Eine andere Sache, die Ihnen auffallen wird, ist die Verwendung der Attribute minOccurs und maxOccurs bei dem Element element; diese Attribute machen es möglich, daß ein Element vom Standard (genau einmal) abweichen und eine bestimmte Anzahl von Malen auftauchen darf. Beispielsweise ermöglichen die Angaben minOccurs="0" und maxOccurs="1", daß ein Element einmal auftaucht oder auch gar nicht. Um dafür zu sorgen, daß ein Element unbegrenzt oft auftauchen darf, können Sie dem Attribut maxOccurs wie in Beispiel 2-4 den Wert »unbounded« zuweisen.

Mehrere Namensräume

Sie haben wahrscheinlich bemerkt, daß ich zwei Schemas definiert habe, was Sie womöglich verwundert hat. Für jeden Namensraum in einem Dokument muß ein eigenes Schema definiert werden. Außerdem können Sie nicht das gleiche externe Schema für beide Namensräume verwenden und einfach beide Namensräume mit diesem Schema verknüpfen. Im Ergebnis benötigt die Verwendung des Präfixes und des Namensraumes ora ein zusätzliches Schema, das ich contents-ora.xsd genannt habe. Sie werden auch das Attribut schemaLocation verwenden müssen, von dem ich vorher sprach, um auf dieses Schema zuzugreifen; fügen Sie aber kein weiteres Attribut hinzu. Statt dessen können Sie ein anderes Paar aus Namensraum- und Schema-Adresse am Ende des Attributwertes einfügen, wie hier gezeigt wird:

<buch xmlns="http://www.oreilly.com/javaxml2"
      xmlns:ora="http://www.oreilly.com"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.oreilly.com/javaxml2 XSD/contents.xsd 
                          http://www.oreilly.com XSD/contents-ora.xsd"
>

Dies bedeutet im wesentlichen, daß die Definitionen für den Namensraum http://www. oreilly.com/javaxml2 im Schema contents.xsd im Verzeichnis XSD/ nachgeschlagen werden sollen. Für den Namensraum http://www.oreilly.com soll das Schema contents-ora.xsd im gleichen Verzeichnis verwendet werden. Sie werden dann die beiden Schemas definieren müssen, die ich Ihnen in den Beispielen 2-4 und 2-5 gezeigt habe. Zu guter Letzt importieren Sie das O’Reilly-Schema in das Java-und-XML Schema, da einige Elemente in letzterem sich auf Attribute im O’Reilly-Schema beziehen:

<xs:import namespace="http://www.oreilly.com" 
           schemaLocation="contents-ora.xsd" />

Diese Importanweisung erklärt sich fast von selbst, also werde ich nicht weiter darauf herumkauen. Sie sollten merken, daß die Arbeit mit mehreren Namensräumen so ziemlich das Komplexeste ist, was Sie in Schemas tun können, und es kann Sie leicht zu Fall bringen (mich hat es zu Fall gebracht, bis Eric van der Vlist mir zu Hilfe kam). Ich empfehle auch einen guten Editor, der XML Schema beherrscht. Während ich im Allgemeinen ungern kommerzielle Produkte empfehle, hat sich in diesem Fall XMLSpy 4.0 (http://www.xmlspy.com) als wunderbar hilfreich erwiesen.

Ich habe nun ein wenig an der Oberfläche sowohl von DTDs als auch von XML Schema gekratzt, und es gibt darüber hinaus noch andere Beschränkungsmodelle, die ich gar nicht behandle! Zum Beispiel gewinnt Relax (und Relax NG, das als Bestandteil das enthält, was früher TREX war) an Einfluß, da es als erheblich einfacher und leichtgewichtiger gilt als XML Schema. Sie können diese Aktivitäten online unter http://www.oasis-open.org/committees/relax-ng/ verfolgen. Für welche Technologie Sie sich auch immer entscheiden, Sie sollten etwas verwenden, mit dem Sie Ihre XML-Dokumente beschränken können. Mit gut gesetzten Beschränkungen sind Validierung und Interoperabilität ein Klacks. Betrachten Sie sich als fertig ausgebildet im Bereich der XML-Beschränkungen, und machen Sie sich für die nächste Station auf diesem Schnelldurchgang bereit: für XML-Transformationen.

Transformationen

So nützlich XML-Transformationen auch sein mögen, sie sind nicht leicht zu implementieren. Tatsächlich wird die Transformation von XML nicht in der Original-XML-1.0-Spezifikation behandelt, statt dessen gibt es drei separate Empfehlungen darüber, wie Transformationen vonstatten gehen sollen. Obwohl eine davon (XPath) auch in einigen anderen XML-Spezifikationen verwendet wird, ist der bei weitem üblichste Verwendungszweck der Komponenten, die ich hier vorstelle, die Transformation von XML von einem Format ins andere.

Da diese drei Spezifikationen eng zusammenhängen und fast immer im Verbund miteinander verwendet werden, gibt es selten eine klare Trennung zwischen ihnen. Dies kann leicht zu einer Diskussion führen, die einfach zu verstehen, aber nicht notwendigerweise technisch korrekt ist. Genauer gesagt wird der Begriff XSLT, der genau genommen für Extensible Stylesheet Transformations steht, oft sowohl für Extensible Stylesheets (XSL) als auch für XPath verwendet. Auf die gleiche Weise wird XSL oft als Sammelbegriff für alle drei Technologien verwendet. In diesem Abschnitt unterscheide ich zwischen den drei Empfehlungen und halte mich an den Buchstaben der Spezifikationen, die diese Technologien beschreiben. Allerdings verwende ich im Interesse der Klarheit im Rest des Buches XSL und XSLT gleichrangig, um den vollständigen Transformationsprozeß zu bezeichnen. Auch wenn dieser Ansatz nicht haargenau der Spezifikation entspricht, wird er sicherlich ihrer Bedeutung gerecht – genau wie die Vermeidung von langatmigen Definitionen einfacher Konzepte, wenn Sie bereits verstehen, was ich meine.

XSL

XSL ist die Extensible Stylesheet Language (etwa: erweiterbare Style-Vorlagen-Sprache). Es ist als Sprache für die Beschreibung von Stylesheets (Style-Vorlagen) definiert. Diese allgemeine Definition läßt sich in zwei Teile aufteilen:

  • XSL ist eine Sprache zur Transformation von XML-Dokumenten.
  • XSL ist ein XML-Vokabular, das dazu dient, die Formatierung von XML-Dokumenten festzulegen.

Die Definitionen sind einander ähnlich, aber die eine beschäftigt sich mit dem Übergang von einem XML-Dokument zu einem anderen, während die andere sich auf die eigentliche Präsentation von Inhalten innerhalb jedes einzelnen Dokuments konzentriert. Es wäre möglicherweise eine klarere Definition zu sagen, daß XSL die Spezifikation dafür darstellt, wie ein Dokument von Format A in Format B übertragen werden soll. Die Komponenten der Sprache beschäftigen sich mit der Verarbeitung und Identifizierung der Konstrukte, mit denen dies erledigt wird.

XSL und Bäume

Das wichtigste Konzept von XSL, das Sie verstehen müssen, ist, daß alle Daten innerhalb der XSL-Verarbeitungsstufen in Baumstrukturen angeordnet sind (siehe Abbildung 2-1). Tatsächlich werden auch die Regeln, die Sie bei der Verwendung von XSL definieren, ihrerseits in einer Baumstruktur abgelegt. Dies ermöglicht eine einfache Verarbeitung der Struktur von XML-Dokumenten. Es werden Templates verwendet, die dem Wurzelelement des XML-Dokuments entsprechen, das gerade verarbeitet wird. Außerdem werden »Blatt«-Regeln auf »Blatt«-Elemente angewendet und bis zu den am tiefsten verschachtelten Elementen hinunter gefiltert. An jeder Stelle dieses Arbeitsfortschritts können Elemente bearbeitet, formatiert (mit einem Style versehen), ignoriert oder kopiert werden, oder es kann eine Menge anderer Dinge mit ihnen getan werden.

Abbildung 2-1: Baumoperationen in XSL
Baumoperationen in XSL

Ein angenehmer Vorteil dieser Baumstruktur ist, daß sie es ermöglicht, die Gruppierung von XML-Dokumenten aufrechtzuerhalten. Enthält das Element A die Elemente B und C und wird Element A verschoben oder kopiert, dann werden die darin enthaltenen Elemente genauso behandelt.

Das beschleunigt die Bearbeitung großer Datenbereiche, die die gleiche Behandlung benötigen, und sorgt dafür, daß sie einfach und knapp im XSL-Stylesheet notiert werden kann. Sie werden mehr darüber erfahren, wie dieser Baum aufgebaut wird, wenn ich im nächsten Abschnitt genauer auf XSLT eingehe.

Formatting Objects

Die XSL-Spezifikation ist fast vollständig damit beschäftigt, Formatting Objects (XSL-FO) zu definieren. Ein Formatting Object basiert auf einem umfangreichen Modell, das aus nachvollziehbaren Gründen Formatting Model heißt. Dieses Modell beschreibt einen Satz von Objekten, die als Eingabe in einen Formatierer übergeben werden. Der Formatierer wendet die Objekte auf das Dokument an, entweder im Ganzen oder nur teilweise, und das Ergebnis ist ein neues Dokument, das alle oder auch nur einige Daten des ursprünglichen XML-Dokuments enthält.

Es liegt in einem Format vor, das durch die Objekte bestimmt wird, die der Formatierer verwendet hat. Da dies ein so vages, schemenhaftes Konzept ist, versucht die XSL-Spezifikation, ein konkretes Modell zu definieren, dem diese Objekte genügen sollten. Mit anderen Worten: Ein umfangreicher Satz von Eigenschaften und Vokabular bildet die Features, die Formatting Objects verwenden können. Dazu gehören die Arten von Bereichen, die durch die Objekte dargestellt werden können, die Eigenschaften von Zeilen, Schriften, Grafik und anderen visuellen Objekten, Formatting Objects in Inline- und Block-Form und eine Vielzahl weiterer Syntaxkonstrukte.

Formatting Objects werden besonders häufig verwendet, wenn XML-Textdaten in binäre Formate wie PDF-Dateien, Bilder oder Dokumentformate wie etwa Microsoft Word konvertiert werden. Für die Transformation von XML-Daten in andere Textformate werden diese Objekte selten explizit verwendet. Auch wenn sie der Stylesheet-Logik zugrundeliegen, werden Formatting Objects selten direkt aufgerufen, da die Ergebnistextdaten oft einer anderen vordefinierten Auszeichnungssprache wie etwa HTML entsprechen.

Da die meisten Anwendungen für Großunternehmen heutzutage zumindest teilweise auf die Webarchitektur aufsetzen und einen Browser als Client verwenden, verbringe ich die meiste Zeit damit, Transformationen in HTML und XHTML zu beschreiben. Obwohl Formatting Objects hier nur am Rande behandelt werden, ist das Thema umfangreich genug, um eine gesonderte Behandlung in einem separaten Buch zu verdienen. Um weitere Informationen zu erhalten, sollten Sie die XSL-Spezifikation unter http://www.w3.org/TR/xsl konsultieren.

XSLT

Die zweite Komponente der XML-Transformationen sind XSL-Transformationen. XSLT ist die Sprache, die die Konvertierung eines Dokuments von einem Format ins andere festlegt (während XSL die Mittel dieser Spezifikation definiert). Die Syntax, die in XSLT verwendet wird, ist grundsätzlich für Texttransformationen vorgesehen, die keine binäre Datenausgabe erzeugen. Zum Beispiel dient XSLT dazu, HTML oder WML (Wireless Markup Language) aus einem XML-Dokument zu erzeugen. In der Tat beschreibt die XSLT-Spezifikation die Syntax eines XSL-Stylesheets ausdrücklicher als die XSL-Spezifikation selbst!

Genau wie XSL ist auch XSLT immer wohlgeformtes, gültiges XML. Für XSL und XSLT ist eine DTD definiert worden, die die erlaubten Konstrukte beschreibt. Aus diesem Grunde brauchen Sie nur die neue Syntax zu erlernen, um XSLT zu verwenden, im Gegensatz zu den völlig neuen Strukturen, die Sie verstehen müssen, um DTDs als solche zu verwenden. Genau wie XSL beruht auch XSLT auf einer hierarchischen Baumstruktur von Daten, in der verschachtelte Elemente Blätter (oder Kindknoten) ihrer Elternknoten sind. XSLT stellt eine Methode zur Verfügung, um Mustervergleiche mit dem ursprünglichen XML-Dokument durchzuführen (unter Verwendung eines XPath-Ausdrucks, was ich als nächstes behandeln werde) und um eine Formatierung der Daten vorzunehmen.

Dies hat zur Folge, daß die Daten einfach ohne die unerwünschten XML-Elementnamen ausgegeben werden oder daß sie in eine komplexe HTML-Tabelle eingefügt werden, die dem Benutzer mitsamt Hervorhebung und Einfärbung angezeigt wird. XSLT stellt auch die Syntax für viele gängige Operationen zur Verfügung, etwa für Fallentscheidungen, für das Kopieren von Baumbereichen, für erweiterte Mustererkennung sowie für die Fähigkeit, auf Elemente innerhalb der eingegebenen XML-Daten in einer absoluten oder relativen Pfadstruktur zuzugreifen. All diese Konstrukte sind entwickelt worden, um den Prozeß der Transformation eines XML-Dokuments in ein neues Format zu vereinfachen. Eine gründliche Behandlung der Sprache XSLT finden Sie in Java und XSLT von Eric Burke (O’Reilly Verlag), in dem hervorragend beschrieben wird, wie man XSLT dazu bringt, mit Java zu arbeiten.

XPath

Der letzte Teil des Puzzles der XML-Transformationen, XPath, bietet einen Mechanismus, um sich auf die große Vielzahl von Element- und Attributnamen in einem XML-Dokument zu beziehen. Wie ich bereits früher erwähnt habe, verwenden viele XML-Spezifikationen bereits XPath, aber die Diskussion hier betrifft nur dessen Verwendung in XSLT. Bei der komplexen Struktur, die ein XML-Dokument aufweisen kann, kann das Auffinden eines bestimmten Elements oder eines Satzes von Elementen schwierig sein. Es wird noch dadurch erschwert, daß der Zugriff auf eine DTD oder einen anderen Satz von Beschränkungen, die die Struktur des Dokuments beschreiben, nicht einfach vorausgesetzt werden kann; Dokumente, die nicht auf Gültigkeit geprüft wurden, müssen trotzdem genau so transformiert werden können wie gültige Dokumente. Um diesen Zugriff auf Elemente zu erledigen, definiert XPath eine Syntax, die mit der Baumstruktur von XML und mit den XSLT-Prozessen und Konstrukten, die diese verwenden, übereinstimmt.

Der Zugriff auf irgendein Element oder Attribut innerhalb eines XML-Dokuments erfolgt am einfachsten dadurch, daß man den relativen Pfad zu diesem Element von demjenigen Element aus angibt, das gerade verarbeitet wird. Mit anderen Worten: Wenn Element B das aktuelle Element ist und die Elemente C und D in B hinein verschachtelt sind, macht ein relativer Pfad sie am einfachsten ausfindig. Dies ähnelt den relativen Pfadangaben, die in den Verzeichnisstrukturen von Dateisystemen verwendet werden. Gleichzeitig definiert XPath aber auch die Adressierung von Elementen von der Wurzel eines Dokuments aus.

Dies beinhaltet den häufigen Fall, daß auf ein Element zugegriffen werden muß, das sich nicht im Bereich des aktuellen Elements befindet; mit anderen Worten, auf ein Element, das nicht in das Element geschachtelt ist, das gerade bearbeitet wird. Zu guter Letzt definiert XPath die Syntax für tatsächliche Mustererkennung: Finde ein Element, dessen Elternelement das Element E ist und das ein Geschwisterelement F hat. Dies schließt die Lücken, die noch zwischen absoluten und relativen Pfaden klaffen. In allen diesen Ausdrücken können genauso auch Attribute verwendet werden, mit entsprechenden Vergleichsmöglichkeiten. Einige Beispiele finden Sie in Beispiel 2-6.

Beispiel 2-6: XPath-Ausdrücke

<!-- Das Element Buch relativ zum aktuellen Element -->
<xsl:value-of select="Buch" />

<!-- Das Element Inhalt, das in das Element Buch verschachtelt ist -->
<xsl:value-of select="Buch/Inhalt" />

<!-- Das Element Inhalt, ausgedrückt durch einen absoluten Pfad -->
<xsl:value-of select="/Buch/Inhalt" />

<!-- Das Attribut name des aktuellen Elements -->
<xsl:value-of select="@name" />

<!-- Das Attribut titel des Elements Kapitel -->
<xsl:value-of select="Kapitel/@titel" />

Da das Eingabedokument oft nicht festgelegt ist, kann ein XPath-Ausdruck dazu führen, daß keine Eingabedaten, ein eingegebenes Element oder Attribut oder viele eingegebene Elemente und Attribute ausgewertet werden. Diese Fähigkeit macht XPath sehr nützlich und praktisch; sie verursacht aber auch die Einführung einiger zusätzlicher Ausdrücke. Das Ergebnis der Auswertung eines XPath-Ausdrucks wird grundsätzlich als Knotenmenge bezeichnet. Dieser Name sollte nicht weiter überraschend sein, da er mit der Idee einer Hierarchie oder Baumstruktur einhergeht. In diesem Zusammenhang ist oft die Rede von Blättern oder auch Knoten. Die resultierenden Knoten können anschließend transformiert, kopiert oder ignoriert werden, oder es kann eine andere erlaubte Operation mit ihnen durchgeführt werden.

Zusätzlich zu den Ausdrücken, die Knotenmengen auswählen, definiert XPath noch einige Knotenmengen-Funktionen wie not() und count(). Diese Funktionen erwarten eine Knotenmenge als Eingabe (üblicherweise in Form eines XPath-Ausdrucks) und schränken die Ergebnisse dann weiter ein. Alle diese Ausdrücke und Funktionen sind gemeinsamer Bestandteil der XPath-Spezifikation und der XPath-Implementierungen; allerdings wird XPath auch oft verwendet, um irgendeinen Ausdruck zu bezeichnen, der der Spezifikation selbst genügt. Wie im Falle von XSL und XSLT wird es so einfacher, über XSL und XPath zu sprechen, auch, wenn es technisch nicht immer ganz korrekt ist.

Mit alledem im Hinterkopf sind Sie zumindest einigermaßen darauf vorbereitet, ein einfaches XSL-Stylesheet zu betrachten, wie es in Beispiel 2-7 gezeigt wird. Auch wenn Sie jetzt noch nicht alles davon verstehen können, wollen wir uns kurz einige Schlüsselaspekte des Stylesheets anschauen:

Beispiel 2-7: XSL-Stylesheet für Beispiel 2-1

<?xml version="1.0"?>

<xsl:stylesheet xmlns:javaxml2="http://www.oreilly.com/javaxml2"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:ora="http://www.oreilly.com"
                version="1.0"
>

  <xsl:template match="javaxml2:buch">
    <html>
      <head>
        <title><xsl:value-of select="javaxml2:titel" /></title>
      </head>
      <body>
        <xsl:apply-templates select="*[not(self::javaxml2:titel)]" />
      </body>
    </html>
  </xsl:template>

  <xsl:template match="javaxml2:inhalt">
    <center>
     <h2>Inhaltsverzeichnis</h2>
    </center>
    <hr />
    <ul>
     <xsl:for-each select="javaxml2:kapitel">
      <b>
       Kapitel <xsl:value-of select="@nummer" />.
       <xsl:text> </xsl:text>
       <xsl:value-of select="@titel" />
      </b>
      <xsl:for-each select="javaxml2:thema">      
       <ul>
        <li><xsl:value-of select="@name" /></li>
       </ul>
      </xsl:for-each>
     </xsl:for-each>
    </ul>
  </xsl:template>

  <xsl:template match="ora:copyright">
    <p align="center"><font size="-1">
     <xsl:copy-of select="*" />
    </font></p>
  </xsl:template>

</xsl:stylesheet>

Template-Zuordnung

Die Basis der gesamten Arbeit mit XSL ist die Template-Zuordnung. Für jedes Element, das Sie in irgendeiner Form ausgeben möchten, geben Sie grundsätzlich ein Template an, das dem Element entspricht. Sie legen ein Template mit dem Schlüsselwort template fest und übergeben den Namen des Elements, das zu diesem Template gehören soll, als Wert des Attributs match an:

<xsl:template match="javaxml2:buch">
  <html>
    <head>
      <title><xsl:value-of select="javaxml2:titel" /></title>
    </head>
    <body>
      <xsl:apply-templates select="*[not(self::javaxml2:titel)]" />
    </body>
  </html>
</xsl:template>

Hier wird das Element buch verarbeitet (aus dem Namensraum, der mit javaxml2 verknüpft ist). Wenn ein XSL-Prozessor das Element buch findet, werden die Anweisungen in diesem Template ausgeführt. In diesem Beispiel werden mehrere HTML-Formatierungs-Tags ausgegeben (die Tags html, head, title und body). Achten Sie darauf, durch die saubere Verwendung von Namensräumen Ihre XSL-Elemente von anderen Elementen (etwa HTML-Elementen) zu unterscheiden.

Anstatt ein Template anzuwenden, können Sie auch die value-of-Anweisung verwenden, um den Wert eines Elements zu erhalten, indem Sie den Elementnamen dem Attribut select zum Vergleich übergeben. In dem Beispiel werden die Zeichendaten im Element title extrahiert und als Titel des auszugebenden HTML-Dokuments verwendet.

Wenn Sie andererseits möchten, daß die Templates angewendet werden, die mit den Kindknoten eines Elements verknüpft sind, verwenden Sie apply-templates. Achten Sie darauf, daß Sie dies auch tun, ansonsten könnten verschachtelte Elemente ignoriert werden! Um die Elemente auszuwählen, auf die Templates angewandt werden sollen, übergeben Sie deren Namen dem select-Attribut. Verwenden Sie als Namen den Wert »*«, werden den verschachtelten Elementen ihre entsprechenden Templates zugeordnet und diese angewandt. In dem Beispiel möchte ich allerdings das Element titel ausschließen (da ich es bereits im Dokumentkopf verwendet habe). Um dies zu bewerkstelligen, verwende ich das Schlüsselwort not und gebe das Element titel auf der self-Achse an, was im Grunde so viel heißt wie »alles (*), außer (not) dem Element titel in diesem Dokument (self::javaxml2:title)«. Dies war nur ein kurzer Überblick, aber ich versuche auch nur, Ihnen genügend Informationen zukommen zu lassen, um mit dem Java-Code loszulegen.

Schleifen

Sie werden in XSL auch häufig den Bedarf entdecken, Schleifen zu verwenden. Schauen Sie sich den folgenden Ausschnitt aus Beispiel 2-7 an:

<xsl:template match="javaxml2:inhalt">
  <center>
   <h2>Inhaltsverzeichnis</h2>
  </center>
  <hr />
  <ul>
   <xsl:for-each select="javaxml2:kapitel">
    <b>
     Kapitel <xsl:value-of select="@nummer" />.
     <xsl:text> </xsl:text>
     <xsl:value-of select="@titel" />
    </b>
    <xsl:for-each select="javaxml2:thema">      
     <ul>
      <li><xsl:value-of select="@name" /></li>
     </ul>
    </xsl:for-each>
   </xsl:for-each>
  </ul>
</xsl:template>

Hier gehe ich in einer Schleife alle Elemente namens kapitel durch, indem ich das Konstrukt for-each verwende. In Java würde dies so aussehen:

for (Iterator i = chapters.iterator(); i.hasNext(  ); ) {
    // Aktion mit jedem Kapitel durchführen
}

Innerhalb der Schleife wird jeweils das nächste gefundene kapitel-Element zum »aktuellen« Element. Bei jedem einzelnen gebe ich die Kapitelnummer aus; dies wird durch das Lesen des Wertes des Attributs nummer (durch value-of) erreicht. Um anzuzeigen, daß ich ein Attribut haben möchte (und nicht, wie üblich, ein Element) stelle ich dem Attributnamen das »@«-Zeichen voran. Das gleiche mache ich, um den Wert des Attributs titel zu erhalten, und in einer Unterschleife gehe ich dann die Themen jedes Kapitels durch.

Beachten Sie den ziemlich unscheinbaren Codeausschnitt <xsl:text> </xsl:text>. Das Konstrukt text stellt eine Möglichkeit zur Verfügung, auf direktem Wege Zeichen in den Ergebnisbaum auszugeben. Dieses Konstrukt erzeugt ein Leerzeichen zwischen dem Wort »Kapitel« und der Kapitelnummer (zwischen dem öffnenden und dem schließenden text-Tag steht ein einzelnes Leerzeichen).

Kopieren

Sie werden auch Fällen begegnen, in denen sämtliche Template-Zuordnung der Welt nicht so nützlich ist wie das einfache Übergeben des unveränderten Inhalts an den Ausgabebaum. Dies ist der Fall mit dem Element copyright:

<xsl:template match="ora:copyright">
  <p align="center"><font size="-1">
   <xsl:copy-of select="*" />
  </font></p>
</xsl:template>

Zusätzlich zu dem bißchen HTML-Formatierung sorgt dieses Template dafür, daß sämtlicher Inhalt des copyright-Elements in den Ausgabebaum kopiert wird, indem es das Konstrukt copy-of verwendet.

Sie werden im Kapitel Web Publishing Frameworks lernen, wie Sie ein Publishing-Framework benutzen können, um die Ergebnisse solcher Transformationen in HTML, PDF oder ein anderes Format umwandeln können. Anstatt Sie jedoch warten zu lassen, zeigt Abbildung 2-2 die umgewandelte Ausgabe von Beispiel 2-1 und des Stylesheets aus Beispiel 2-6.

Abbildung 2-2: Ergebnis der XSL-Transformation
Ergebnis der XSL-Transformation

Ich merke, daß ich beinahe durch dieses Material geflogen bin, aber noch einmal, ich versuche lediglich, Ihnen die Grundlagen zu vermitteln, um Sie zum interessanteren Stoff zu führen, nämlich zu Java und XML. Halten Sie ein Handbuch bereit, und plagen Sie sich nicht zu sehr damit.

Und mehr…

Da ich Sie nun zu der Annahme verleitet habe, daß das alles zum Thema XML war, möchte ich noch einmal sichergehen, daß Sie sich merken, daß es noch eine Vielzahl weiterer Technologien mit XML-Bezug gibt. Ich kann sie hier wahrscheinlich nicht alle unterbringen. Sie sollten einen kurzen Blick auf Dinge wie CSS (Cascading Stylesheets) und XHTML werfen, wenn Sie Webdesign betreiben. Dokumentautoren werden sicher mehr über XLink und XPointer herausfinden wollen (die ich beide im Kapitel Ausblick behandle). XQL (XML Query Language) wird die Datenbankprogrammierer interessieren. Mit anderen Worten: Es gibt im Moment für so ziemlich jede Technologiesparte etwas XML. Werfen Sie einen Blick auf die Aktivitäten-Seite unter http://www.w3.org/XML und schauen Sie, was für Sie interessant aussieht.

Und was kommt jetzt?

Mit etwas Basiswissen über XML sind Sie nun in der Lage, in den Java-Bereich des Themas einzusteigen. Im nächsten Kapitel stelle ich Ihnen SAX vor, die Simple API for XML. Dies ist die Grundlage der Java-und-XML-APIs, und sie wird den Anfang liefern, wenn ich Ihnen zeige, wie Sie XML in Ihren Java-Anwendungen benutzen können. Sie werden lernen, Dokumente zu lesen, verschiedene Optionen für die DTD- und Schema-Validierung einzustellen, die Namensraum-Verarbeitung zu verwenden und noch mehr, und Sie werden verstehen, wann SAX das richtige Werkzeug für eine bestimmte Aufgabe ist. Werfen Sie Ihren Editor an, und blättern Sie um.