vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Tag 7

XML-Entities

Nachdem Sie wohl geformtes und gültiges XML kennen gelernt haben, erhalten Sie nun die Gelegenheit, sich mit einer besonderen Klasse von XML-Objekten zu beschäftigen: den XML-Entities. Die Schemata, die Sie geschrieben haben, waren eigentlich so etwas wie spezialisierte externe Entities, die durch Ihr XML-Dokument referenziert wurden. Heute lernen Sie etwas über:

7.1 Zwei Arten von Entities

Am 4. Tag haben Sie einige Beispiele für Entities bei DTDs gesehen, jedoch standen die verschiedenen Entity-Typen, die XML unterstützt, nicht im Mittelpunkt des Interesses. Heute untersuchen Sie verschiedene XML-Entity-Typen, vergleichen sie miteinander und lernen Methoden kennen, mit denen man bestimmte Schwierigkeiten bei der Programmierung überwinden kann, und mit denen Sie Kurzbefehle und Einsparungen einsetzen und bei der Programmierung die Modularität bereitstellen.

Zwei Arten von Entities stehen zur Verfügung, um Daten einzukapseln. Alle, die HTML- Seiten erstellen, kennen die vordefinierten allgemeinen Entities als eine Methode, Zeichen darzustellen, die man mit reservierten Markup-Zeichen verwechseln könnte. Wenn man in einem HTML-Dokument die Zeichen <, > oder & wiedergeben will, muss man das Sonderzeichen zunächst als Entity eingeben. Die Syntax für Entities dieser Art ist bei HTML

&entity_name;

Wenn der Browser bei seiner Interpretation der Seite die HTML-Entity auflöst, findet eine Ersetzung statt. Das Zeichen, das sie repräsentiert, nimmt den Platz der Entity-Phrase ein. Das Gleiche gilt bei XML. Zum Zeitpunkt der Verarbeitung der Dokument-Instanz findet eine Ersetzung statt. Der Parser löst die Entity auf und platziert den String, auf den verwiesen wird, in einer Reihe mit dem umliegenden Inhalt.

Parameter-Entities werden nur in externen Schemata wie etwa DTDs definiert und verwendet, obwohl auch andere Schemasprachen die Vorrichtungen zur Entity- Deklaration haben. Parameter-Entities können die Tipparbeit für einen Entwickler erheblich reduzieren, indem sie allgemein verwendete Phrasen in kleinen Entity-Objekten ablegen. Parameter-Entities bieten DTD-Autoren auch ein Mittel, wie man DTD- Untermengen entwickelt und logische Strukturen externer DTDs in beinahe modularer Weise wiederverwendet. Sie werden die beiden Arten von Entities heute kennen lernen und sehen, wie man sie in XML-Instanzen programmiert.

7.2 Allgemeine Entities

Allgemeine Entities bieten in HTML eine Methode, wie man Zeichen programmiert, die nicht im normalen ASCII-Zeichensatz enthalten sind oder die mit der Auszeichnung in Konflikt geraten können. XML kümmert sich weniger um nicht standardgemäße Zeichen, etwa solche, die außerhalb des normalen Bereichs des ASCII-Zeichensatzes liegen. Dies ist deshalb der Fall, weil XML so gestaltet wurde, dass es statt ASCII den weit umfangreicheren Zeichensatz Unicode nutzen kann. Beim Ansatz mit dem Unicode- Zeichensatz von 16 Bit werden 65.536 mögliche Zeichen bereitgestellt, während das 7-Bit- ASCII nur 128 Zeichen zulässt und der 8-Bit-Satz 256 Zeichen umfasst. Beim Bereich des ASCII-Zeichensatzes kann es schnell passieren, dass der verfügbare »Leerraum« erschöpft ist. Bevor Unicode zum Einsatz kam, mussten einige Sprachen bei HTML grafisch dargestellt werden, weil der ASCII-Satz zu wenig Raum bot, um alle erforderlichen Zeichen einzubringen. Einige europäische Sprachen füllen die 256 Zeichen des ASCII- Satzes recht schnell aus. Vor allem asiatische Sprachen umfassen eine große Anzahl von Zeichen- und Glyphensätzen und kombinieren sie so, dass Zehntausende von Ideogrammen entstehen. Der 16-Bit-Unicode-Standard soll diesen Bedarf befriedigen. Für den Fall jedoch, dass er an seine Grenzen stößt, unterstützt XML auch den 32-Bit- Unicode-Standard.

XML schließt fünf eingebaute Entities ein, die dem Entwickler helfen sollen, Auszeichnungsprobleme zu vermeiden. Tabelle 7.1 zeigt, welche dies sind.

Entity

Beschreibung

&amp;

Ampersand (&)

&apos;

Apostroph (')

&gt;

Größer als (>)

&lt;

Kleiner als (<)

&quote;

Anführungszeichen (»)

Tabelle 7.1: Fünf vordefinierte XML-Entities 

Über den vordefinierten Entity-Satz hinaus, den XML bereitstellt, können Sie Ihre eigenen Entities aufstellen, genau wie Sie ein Element deklarieren können. Entities können einem Zeit und Tastenanschläge ersparen. Wiederholte und lästige Aufgaben können vereinfacht werden, wenn man Entities definiert, die bei der Interpretation mit einem XML-Prozessor durch Daten ersetzt werden. Die grundsätzliche Syntax für die Deklaration einer allgemeinen Entity-Referenz in einer DTD lautet:

<!ENTITY entityname zu ersetzende Daten>

Die Syntax zur Verwendung der Entity in einer XML-Instanz lautet:

&entityname;

In anderen Schemasprachen ist es nicht einfach, Entities zu deklarieren. Für den heutigen Tag verwenden Sie DTDs, um Entity-Deklarationen zu erstellen. Beachten Sie, dass allen Entities, die bislang vorgestellt wurden, ein Ampersand-Zeichen vorausgeht (&), unmittelbar gefolgt vom Namen der Entity und einem Semikolon. Die Entity bildet ein Proxy für die Entity-Definition im Schema. Zum Zeitpunkt der Interpretation durch einen XML-Prozessor wird der gesamte Entity-String durch die Ersetzung mit der Entity-Referenz aufgelöst.

Die Verwendung dieses Mechanismus zum Erzeugen von Entities ist besonders wertvoll bei XML-Instanzen, die sich wiederholende Daten enthalten, die während der Lebensspanne eines Dokuments anfällig für Veränderungen sind. Man könnte zum Beispiel einen gesetzlichen Vertrag mit Entities auszeichnen, die für beide Seiten des Abkommens stehen. Die Entity-Ersetzung wäre Garant dafür, dass die Daten, die die Parteien beschreiben, zur Laufzeit aufgelöst würden. Listing 7.1 zeigt den Ausschnitt eines Verkaufsvertrags, der als wohl geformtes und gültiges XML-Dokument ausgezeichnet ist und für die Vertragsparteien Entities einsetzt. Erzeugen Sie dieses Dokument mit einem Texteditor und speichern es unter vertrag01.xml.

Listing 7.1: Ausschnitt aus einem Vertrag, abgefasst in XML mit Entities - vertrag01.xml

 1: <?xml version="1.0"?>
2: <!-- listing 7.1 - vertrag01.xml -->
3:
4: <!DOCTYPE vertrag SYSTEM "vertrag01.dtd">
5: <vertrag>
6: <para1>&kaeufer; erklaert sich damit einverstanden, die unten
7: definierte Immobilie gemaess den Bedingungen dieses Vertrags
8: zu erwerben.</para1>
9: <para2 abschnitt="1">&kaeufer; wird Eigentuemer der Immobilie
10: die unten beschrieben ist, wofuer &kaeufer; sich einverstanden erklaert...zu bezahlen </para2>
11: </vertrag>

Das Wurzelelement vertrag (Zeilen 2-11) enthält die Elemente para1 (Zeilen 6-8) und para2 (Zeilen 9-10). Das Element para1 enthält ein abschnitt-Attribut mit dem Wert 1. Zeile 4 enthält eine doctype-Deklaration, die das Element vertrag als Wurzel identifiziert, und deklariert eine externe DTD mit der URI vertrag01.dtd. In den Zeilen 6, 9 und 10 wird die Entity &käufer; eingeschlossen.

Die DTD für dieses Dokument muss nicht nur die Beziehungen von Element und Attribut deklarieren, sondern auch die Entity-Referenz bereitstellen, die die Entity &kaeufer; ersetzt, nachdem der XML-Prozessor sie aufgelöst hat. Angenommen, der Käufer in diesem Vertrag ist Devan Shepherd. Dann kann man die Entity-Referenz in der DTD folgendermaßen eingeben:

<!ENTITY kaeufer "Devan Shepherd">

Dieser DTD-Ausschnitt weist den XML-Prozessor an, den String David Shepherd für jedes Vorkommen der kaeufer-Entity in die XML-Instanz einzusetzen. Der Prozessor kann jedes Vorkommen lokalisieren, weil er die spezielle Syntax &kaeufer; erkennt. Listing 7.2 zeigt eine vollständige DTD für die Dokument-Instanz vertrag01.xml. Erzeugen Sie dieses DTD-Beispiel und speichern Sie es unter vertrag01.dtd im gleichen Verzeichnis, in dem Ihre Datei vertrag01.xml abgelegt ist.

Listing 7.2: Eine DTD mit der Deklaration einer Entity-Referenz - vertrag01.dtd

 1: <?xml version="1.0" encoding="UTF-8"?>
2: <!-- Listing 7.2 - vertrag01.dtd -->
3:
4: <!ELEMENT vertrag (para1, para2)>
5: <!ELEMENT para1 (#PCDATA)>
6: <!ELEMENT para2 (#PCDATA)>
7: <!ATTLIST para2
8: abschnitt CDATA #REQUIRED
9: >
10: <!ENTITY kaeufer "Devan Shepherd">

Die Zeilen 4-9 deklarieren die Element- und Attributsstruktur für das XML-Dokument. Ihre Interpretation besagt, dass das vertrag-Element einen Elementinhalt enthält, insbesondere die abgeleiteten Elemente para1 und para2. Das Element para1 enthält nur Text (#pcdata), para2 ebenfalls. Das Element para2 hat auch ein obligatorisches abschnitt-Attribut, das nur Zeichendaten (cdata) enthält. Zeile 10 definiert die Entity-Referenz und zeigt an, dass Devan Shepherd die Referenz für die kaeufer-Entity ist.

Laden Sie Ihr Dokument vertrag01.xml in den Browser Microsoft Internet Explorer, um sich das Ergebnis der Entity-Ersetzung anzusehen. Der MSXML löst die Entity auf und ersetzt sie mit dem Referenzstring, den er aus der DTD erhält. Abbildung 7.1 zeigt dieses Resultat. Beachten Sie, dass der String Devan Shepherd jetzt dort steht, wo vor dem Parsen des Dokuments die Entity &kaeufer; stand.

Stellen Sie sich vor, Sie müssten ein ganzes Dokument aus mehreren Seiten auf diese Weise auszeichnen. Bei einem Kaufvertrag für Immobilien etwa können Sie schnell ein Dutzend DIN A 4-Seiten mit Text bekommen, mit ein paar Dutzend &kaeufer;-Entities bei den verschiedenen Vertragsklauseln. Die Entity-Ersetzung erspart es Ihnen, sich jedes Mal vergewissern zu müssen, dass jeder Verweis auf den Käufer korrekt geschrieben ist und an genau der richtigen Stelle im Vertrag auftaucht, damit dieser auch legal und bindend ist. Noch wichtiger aber, wenn Sie wieder einmal einen Kaufvertrag brauchen, müssen Sie die Entity-Referenz in der DTD nur einmal ändern, um an jeder passenden Stelle im Vertrag den neuen Käufernamen einsetzen zu können.

Abbildung 7.1:  Beim Dokument vertrag01.xml wurden alle Entities aufgelöst.

Dies ist äußerst ökonomisch, was die Wiederverwendbarkeit des Dokuments und die Datenmodularität betrifft. Denkt man dieses einfache Beispiel aus dem Rechtswesen weiter, sieht man, dass ganze Sammlungen standardmäßiger Gesetzestexte - wie Präzedenzfälle, die Parteien einer Vereinbarung oder einer Klage, zeitliche Umstände usw. - in einer Dokument-Instanz durch die Entity-Ersetzung erzeugt werden können.

Der Umfang der Referenz auf eine Entity ist unbegrenzt; Entities stellen daher eine praktische Methode dar, wie man Objekte oder Textstrings, die häufig wiederverwendet werden, ersetzen kann - vor allem, wenn sie lang sind.

7.3 Parameter-Entities

Die Parameter-Entity wird in einer DTD programmiert, um Informationen zu transportieren, die in den Auszeichnungs-Deklarationen verwendet werden. Normalerweise wird mit Parameter-Entities ein Satz gebräuchlicher Attribute definiert, den mehrere Elemente gemeinsam verwenden, oder ein Link auf eine externe DTD bereitgestellt. Diejenigen, die auf Referenzen zielen, die ganz innerhalb der DTD liegen, werden interne Parameter-Entities genannt. Diejenigen, die auf Daten und Objekte außerhalb der aktuellen DTD verweisen, nennt man externe Parameter-Entities.

Parameter-Entities sind nützlich, aber es kann recht schwierig werden, sie auszulesen. Sie werden in einer DTD mit einem Prozentzeichen (%) in der Referenz und in der Deklaration programmiert. Das Prozentzeichen ist ein Flag, das verwendet wird, um anzuzeigen, dass es sich um eine Parameter-Entity und nicht um eine allgemeine Entity handelt. Die Syntax für die Parameter-Entity in einer DTD lautet:

<!ENTITY % entityname Definition_der_Entity>

Das Prozentzeichen muss durch ein Leerzeichen vom Entity-Namen abgetrennt sein. Die Definition der Entity kann ein beliebiger gültiger String sein. Der String wird an den Stellen ersetzt, wo die Entity in der DTD verwendet wird. Anders gesagt, eine interne Parameter-Entity funktioniert wie eine allgemeine Entity, außer dass die Ersetzung in der DTD stattfindet, nicht in der Dokument-Instanz.

Angenommen, Sie wollen eine DTD für eine Rechnung erzeugen und dieses Dokument enthält eine Rechnungsanschrift, eine Lieferadresse, eine Käuferadresse und die Adresse eines Warenhauses. Wenn die Adressen ihrer Struktur nach alle recht ähnlich aufgebaut sind, könnten Sie eine Parameter-Entity verwenden, um die Adressenstruktur einmal zu erstellen und sie in der restlichen DTD nach Bedarf wiederzuverwenden. Der Adressteil der DTD könnte so aussehen:

<!ENTITY % adresse 
"strasse CDATA #REQUIRED
strasse2 CDATA #IMPLIED
stadt CDATA #REQUIRED
staat CDATA #REQUIRED
plz CDATA #REQUIRED">

In diesem Fall verweist die adresse-Entity auf einen Satz von Attributs-Deklarationen. Ein Prozentzeichen, das anzeigt, dass eine Parameter-Entity deklariert wird, folgt auf jedes ENTITY-Schlüsselwort. Die Parameter-Entity heißt adresse und verweist auf den String von Attributs-Deklarationen, der zwischen den doppelten Anführungszeichen (") enthalten ist.

Wenn Sie dies erstellt haben, können Sie die adresse-Entity verwenden, um ein bestimmtes Muster von Attributszuweisungen auf Elemente, die von der DTD beschränkt werden, zu ersetzen. Um die Attribute der Rechnungsanschrift in einem Element rechnung zu validieren, können Sie Folgendes einfügen:

<!ELEMENT   rechnung   (#PCDATA)>
<!ATTLIST rechnung %adresse;>

Das Element rechnung enthält geparste Zeichendaten (#pcdata) und hat Attribute. Die Attribute stammen aus der %adresse-Entity, die an anderer Stelle in der DTD deklariert wurden. Das Prozentzeichen wird hier dazu verwendet, um den Namen der Entity einzuleiten, es ist aber kein Leerzeichen zwischen dem Prozentzeichen und dem dazugehörigen Namen zulässig. So erkennt der Parser, dass es sich hierbei um eine Entity handelt. Die Referenz-Deklaration der Entity erfordert das Leerzeichen nach dem Prozentzeichen, um sie von Entities zu unterscheiden.

Löst der XML-Parser die Entity in der DTD auf, dann ist das Resultat effektiv das gleiche wie bei einer DTD, die so programmiert wurde:

<!ELEMENT   rechnung        (#PCDATA)>
<!ATTLIST rechnung
strasse CDATA #REQUIRED
strasse2 CDATA #IMPLIED
stadt CDATA #REQUIRED
staat CDATA #REQUIRED
plz CDATA #REQUIRED>

Die Entity lässt die Ersetzung durch die Adress-Attribute anstelle der Entity %adresse zu. Um das Beispiel mit der Rechnung wieder aufzunehmen, eine komplexere DTD könnte in etwa so aussehen:

<!ELEMENT   gesamtrechnung (rechnung, versand, käufer, warenhaus)>
<!ELEMENT rechnung (#PCDATA)>
<!ATTLIST rechnung %adresse;>
<!ELEMENT versand (#PCDATA)>
<!ATTLIST versand %adresse;>
<!ELEMENT käufer (#PCDATA)>
<!ATTLIST käufer %adresse;>
<!ELEMENT warenhaus (#PCDATA)>
<!ATTLIST warenhaus %adresse;>
<!ENTITY % adresse
"strasse CDATA #REQUIRED
strasse2 CDATA #IMPLIED
stadt CDATA #REQUIRED
staat CDATA #REQUIRED
plz CDATA #REQUIRED">

Dies erspart eine Mühe, die man sich andernfalls machen müsste, einschließlich des Aufstellens einer vollständigen Attributsliste für jedes rechnung-, versand-, kaeufer- und warenhaus-Element.

Externe Entities funktionieren genauso, nur dass die Referenzen in einem getrennten Dokument liegen. Somit ist die DTD in Wirklichkeit die Sonderform einer externen Parameter-Entity.

7.4 Entities in anderen Schemasprachen

Sie haben heute viele Beispiele für Entities gesehen, die alle die DTD-Deklarationen verwenden. Es ist nicht leicht, Entities in anderen Schemasprachen zu deklarieren. Der einfachste Weg, um zum Beispiel eine Entity-Ersetzung in XSD zu deklarieren, ist, ein spezielles Element zu erzeugen und dann den Elementinhalt festzulegen. Auf diese Weise kann man das Element als Entity-Referenz einsetzen. Außerdem müsste man einen eindeutigen Namensraum deklarieren, um dies zu erreichen und sicherstellen, dass das erzeugte Element an diesen Namensraum gebunden ist.

Stellen Sie sich zum Beispiel vor, dass Sie mit diesem Ansatz das Äquivalent für eine Zeichen-Entity erstellen wollen, die einen Ersetzungsstring repräsentiert. Vielleicht möchten Sie einen längeren Satz, etwa den Titel dieses Buchs, »XML in 21 Tagen«, in eine Kurzform bringen. In Ihrem XSD-Schema können Sie ein Element erzeugen und ihm einen festen Wert geben. Die XSD-Deklaration sieht dann so aus:

<xsd:element name="tyx21" fixed="M + T XML in 21 Tagen, Zweite Ausgabe">

Ein Dokument der XML-Instanz, das dieses Element verwendet, kann es als einem bestimmten Namensraum zugehörig einschließen, und wenn es durch den Parser aufgelöst wird, kann es expandiert werden. Hier sehen Sie das Beispiel eines Dokumentausschnitts, der das Element mit festgelegtem Inhalt verwendet:

<?xml version="1.0"?>
<nachricht xmlns="meinedinge/nachricht"
xmlns:ent="meinedinge/nachricht/entities">

... weitere Auszeichnungen

<Einleitung>Willkommen zu <ent:tyx21>. Dies ist ein Buch über...
</Einleitung>

... weitere Auszeichnungen

</nachricht>

Wenn ein XML-Prozessor dies auflöst, wird das Element <ent:tyx21> durch den String M + T XML in 21 Tagen, Zweite Ausgabe ersetzt.

7.5 Zusammenfassung

Heute haben Sie gesehen, wie man Entities in XML als Objekte verwenden kann, deren Aufgabe es ist, die Daten, auf die verwiesen wird, an der Stelle aufzunehmen, an der ein XML-Prozessor die Entity auflöst. In einigen Fällen sind diese Ersetzungen hilfreich, damit Probleme bei der Auszeichnung vermieden werden können. Das ist zum Beispiel der Fall, wenn ein Sonderzeichen wie ein »Kleiner als«-Zeichen (<) oder ein Ampersand (&) durch eine Entity angezeigt und später durch den Parser aufgelöst wird. XML gestattet Ihnen, Ihre eigenen Entities zu erstellen, um sich wiederholende Aufgaben mit weniger Aufwand zu erledigen. Sie können damit auch Daten ersetzen, die sich häufig ändern, oder sich Code-Module zunutze machen, die sich wiederverwenden lassen.

7.6 Fragen und Antworten

Frage:
Welche zwei Arten von Entities gibt es und wie unterscheiden sie sich?

Antwort:
XML stellt allgemeine Entities und Parameter-Entities zur Verfügung. Allgemeine Entities können entweder intern oder extern sein und stellen eine Methode dar, Datenobjekte zu ersetzen. Parameter-Entities existieren nur innerhalb einer DTD, nicht in der Dokument-Instanz. Parameter-Entities sind ein Mittel der Ersetzung oder der Code-Modularität.

Frage:
Wie kann ein Parser in einer DTD feststellen, ob es sich um eine Parameter-Entity oder um eine allgemeine Entity handelt?

Antwort:
Die Referenz bei einer Parameter-Entity wird am Ort der Referenz-Deklaration durch ein Ampersand-Zeichen angezeigt, dem zumindest ein Leerzeichen und der Name der Entity folgen.

7.7 Übung

Die Lösungen finden Sie in Anhang A.

Verwenden Sie die Music Collection Markup Language (MCML)-Instanz aus der Übung des 4. Tages und modifizieren Sie sie so, dass Sie für jedes cd-Element in Ihrer Sammlung ein abgeleitetes Element stil einfügen. Erstellen Sie eine &stil;-Entity mit einer Textbeschreibung, die in etwa so aussieht: »Diese CD ist eine Zusammenstellung der größten Hits dieses Künstlers und ist typisch für den Stil, den wir mittlerweile genießen können.« Wenn Sie damit fertig sind, laden Sie Ihr Dokument cd.xml in einen Browser, um sicherzustellen, dass die Entities aufgelöst werden.



vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbackKapitelanfangnächstes Kapitel


© Markt+Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH