Parameter-Entities

(Auszug aus "XML in a Nutshell" von Elliotte Rusty Harold & W. Scott Means)

Es ist nicht ungewöhnlich, dass sich mehrere Elemente alle oder Teile der gleichen Attributlisten und Inhaltsspezifizierungen teilen. Zum Beispiel wird jedes Element, das ein einfacher XLink ist, die Attribute xlink:type und xlink:href besitzen sowie möglicherweise xlink:show und xlink:actuate. In XHTML enthalten die Elemente th und td mehr oder weniger den gleichen Inhalt. Das Wiederholen der gleichen Inhaltsspezifizierungen oder Attributlisten in mehreren Element-Deklarationen ist lästig und fehlerträchtig. Es ist schnell passiert, dass man der Deklaration einiger der Elemente ein neu definiertes Kindelement hinzufügt, es bei anderen aber vergisst.

Stellen Sie sich zum Beispiel eine XML-Anwendung zur Auflistung von Immobilien vor, die getrennte Elemente für Apartments, Einliegerwohnungen, zu verkaufende Lofts, Wohnungen und Häuser enthält. Die Element-Deklarationen könnten so aussehen:

<!ELEMENT apartment         (adresse, größe, zimmer, bäder, miete)>
<!ELEMENT einliegerwohnung  (adresse, größe, zimmer, bäder, miete)>
<!ELEMENT loft              (adresse, größe, zimmer, bäder, preis)>
<!ELEMENT wohnung           (adresse, größe, zimmer, bäder, preis)>
<!ELEMENT haus              (adresse, größe, zimmer, bäder, preis)>

Unter diesen Deklarationen gibt es eine Menge Überschneidungen, d.h. sich wiederholenden Text. Und falls Sie später beschließen, ein weiteres Element hinzuzufügen, wie etwa verfügbarkeitsdatum, müssen Sie es allen fünf Deklarationen hinzufügen. Es wäre besser, eine Konstante zu definieren, die die gemeinsamen Bestandteile der Inhaltsspezifizierungen für alle fünf Arten von Auflistungen enthält, und aus der Inhaltsspezifikation jedes einzelnen Elements auf diese Konstante zu verweisen. Um dann etwas zu allen Listen hinzuzufügen oder aus ihnen zu entfernen, müssen Sie nur die Definition der Konstante ändern.

Ein offensichtlicher Kandidat an dieser Stelle ist die Entity-Referenz. Allerdings dürfen allgemeine Entity-Referenzen keinen Ersetzungstext für eine Inhaltsspezifizierung oder eine Attributliste enthalten, sondern nur für Teile der DTD, die in das XML-Dokument selbst eingefügt werden. Stattdessen bietet XML ein neues Konstrukt, das ausschließlich für den Einsatz innerhalb von DTDs bestimmt ist: das Parameter-Entity, auf das über eine Parameter-Entity-Referenz verwiesen wird. Parameter-Entities verhalten sich fast wie allgemeine Entities und werden auch genauso deklariert. Allerdings benutzen sie ein %-Zeichen anstelle eines &-Zeichens und können nur in einer DTD eingesetzt werden, während allgemeine Entities nur im Dokumentinhalt vorkommen dürfen.

Syntax von Parameter-Entities

Eine Parameter-Entity-Referenz wird fast genauso deklariert wie eine allgemeine Entity-Referenz. Zwischen <!ENTITY und den Namen des Entitys wird jedoch zusätzlich ein Prozentzeichen gesetzt, z. B.:

<!ENTITY % immobilien_inhalt  "adresse, größe, zimmer, bäder">
<!ENTITY % miete_inhalt       "miete">
<!ENTITY % kaufpreis_inhalt   "preis">

Parameter-Entities werden auf die gleiche Weise dereferenziert wie allgemeine Entity-Referenzen, nur dass anstelle eines Ampersand ein Prozentzeichen erscheint:

<!ELEMENT apartment         (%immobilien_inhalt;, %miete_inhalt;)>
<!ELEMENT einliegerwohnung  (%immobilien_inhalt;, %miete_inhalt;)>
<!ELEMENT loft              (%immobilien_inhalt;, %kaufpreis_inhalt;)>
<!ELEMENT wohnung           (%immobilien_inhalt;, %kaufpreis_inhalt;)>
<!ELEMENT haus              (%immobilien_inhalt;, %kaufpreis_inhalt;)>

Wenn der Parser diese Deklarationen liest, setzt er den Ersetzungstext des Entitys für die Entity-Referenz ein. Um nun beispielsweise dem Inhaltsmodell aller fünf aufgelisteten Typen das Element verfügbarkeitsdatum hinzuzufügen, müssen Sie das Entity immobilien_inhalt lediglich folgendermaßen erweitern:

<!ENTITY % immobilien_inhalt "adresse, größe, zimmer, bäder, verfügbarkeitsdatum">

Diese Technik funktioniert auch für Attributtypen sowie Elementnamen.

Der Trick beschränkt sich auf externe DTDs. Interne DTD-Teilmengen lassen es nicht zu, dass Parameter-Entity-Referenzen nur Teil einer Markup-Deklaration sind. Parameter-Entity-Referenzen können jedoch in internen DTD-Teilmengen dazu verwendet werden, um eine oder mehrere ganze Markup-Deklarationen einzufügen, typischerweise durch externe Parameter-Entities.

Parameter-Entities umdefinieren

Parameter-Entity-Referenzen sind deshalb besonders mächtig, weil sie umdefiniert werden können. Wenn ein Dokument sowohl eine externe als auch eine interne DTD-Teilmenge enthält, kann die interne DTD-Teilmenge neuen Ersetzungstext für die Entities festlegen. Wurden die ELEMENT- und die ATTLIST-Deklarationen in der externen Untermenge der DTD indirekt mit Hilfe von Parameter-Entity-Referenzen geschrieben, anstatt mit den eigentlichen Elementnamen, kann die interne DTD-Teilmenge die DTD des Dokuments verändern. Ein einzelnes Dokument könnte beispielsweise die Listen durch ein Kindelement schlafzimmer erweitern, indem das Entity immobilien_inhalt folgendermaßen umdefiniert würde:

<!ENTITY % immobilien_inhalt "adresse, größe, zimmer, schlafzimmer, bäder, verfügbarkeitsdatum">

Falls sich Entity-Deklarationen gegenseitig stören, hat die erste Deklaration Vorrang. Ein Parser liest die interne DTD-Teilmenge zuerst. Deshalb wird ihre Definition von immobilien_inhalt verwendet. Wenn der Parser dann die externe DTD-Teilmenge liest, enthält jede Deklaration, die das Entity immobilien_inhalt besitzt, ein Kindelement schlafzimmer, das ansonsten nicht vorhanden wäre.

Modulares XHTML, mit dem wir uns unter XML im Web befassen, setzt diese Technik in großem Stil ein, um es bestimmten Dokumenten zu erlauben, nur auf die Teilmenge von HTML zuzugreifen, die sie tatsächlich benötigen.

Externe DTD-Teilmengen

Echte DTDs können ziemlich komplex werden. Die SVG-DTD ist mehr als 1.000 Zeilen lang. Die XHTML 1.0-Strict-DTD (die kleinste der drei XHTML-DTDs) ist mehr als 1.500 Zeilen lang. Und das sind nur mittelgroße DTDs. Die DocBook-XML-DTD ist mehr als 11.000 Zeilen lang. Es ist schwierig, mit einer solch langen DTD zu arbeiten, sie zu verstehen und sie zu verändern, wenn sie in einer einzigen, monolithischen Datei gespeichert ist.

Glücklicherweise können DTDs in unabhängige Teile aufgeteilt werden. Die DocBook-DTD ist beispielsweise auf 28 Einzelteile verteilt, die verschiedene Bereiche der Spezifikation abdecken – ein Teil für Tabellen, einer für Entity-Deklarationen, einer für Notationen usw. Diese unterschiedlichen Teile werden dann zum Zeitpunkt der Validierung mit Hilfe externer Parameter-Entity-Referenzen kombiniert.

Ein externes Parameter-Entity wird mittels einer normalen ENTITY-Deklaration mit einem Prozentzeichen deklariert, genau wie ein normales Parameter-Entity. Anstatt jedoch den Ersetzungstext direkt einzufügen, enthält die Deklaration das Schlüsselwort SYSTEM, gefolgt von einer URL auf den DTD-Teil, den sie einsetzen will. Die folgende ENTITY-Deklaration beispielsweise definiert ein externes Entity mit der Bezeichnung namen, dessen Inhalt der Datei unter der relativen URL namen.dtd entnommen wird. Die Parameter-Entity-Referenz %namen; fügt den Inhalt dieser Datei dann in die aktuelle DTD ein:

<!ENTITY % namen SYSTEM "namen.dtd">
%namen;

Sie können je nach Bedarf relative oder absolute URLs verwenden. In den meisten Situationen sind relative URLs praktischer.

  

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema XML bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

  


Copyright © 2005 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XML in a Nutshell" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O’Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de