XML/DTD/Entities
Entities (Singular: Entity) sind definierte Kürzel. Vielleicht kennen Sie aus Textverarbeitungsprogrammen die Möglichkeit, Textbausteine zu definieren, die dann über ein Menü oder Tastaturkürzel sehr schnell in den aktuellen Text einfügbar sind. Genau diese Funktionalität ist eine der Aufgaben von Entities.
Entities in XML können jedoch mehrere Funktionen haben. So sind die Textbausteine, die Sie damit definieren können, einerseits in Anwendungsdateien verfügbar. Entities, die nur innerhalb von DTD-Definitionen eine Kürzel-Funktion haben, oder Entities, die den Bezug zu externen Datenquellen herstellen, und Entities, die Umschreibungen für spezielle Zeichen realisieren.
Entities kommen auch in bekannten Auszeichnungssprachen wie HTML vor. Wenn Sie in HTML beispielsweise Zeichenfolgen wie ü
notieren, dann wenden Sie Entities an, die für HTML definiert wurden. Um Entities in XML zu verstehen, müssen Sie sich jedoch von der eingeschränkten Funktionalität der HTML-Entities lösen.
Inhaltsverzeichnis
Schema zur Definition von Entities
Entities werden innerhalb einer DTD nach folgendem Schema notiert:
<!ENTITY [%] Name [SYSTEM|PUBLIC] "Wert" [zusätzliche Angaben] >
Die Definition eines Entities beginnt mit einer öffnenden spitzen Klammer <. Dahinter folgt unmittelbar anschließend ein Ausrufezeichen ! und dahinter, in Großbuchstaben, das Schlüsselwort ENTITY. Anschließend folgt bei Parameter Entities für DTD-Bausteine ein Prozentzeichen %, bei anderen Entity-Definitionen nicht. In allen Fällen folgt jedoch ein Name für das Entity. Den Namen können Sie frei wählen. Er muss jedoch den Regeln für Namen in XML genügen. Hinter dem Namen kann eines der Schlüsselwörter SYSTEM oder PUBLIC folgen, und zwar im Falle von Entities für externe Ressourcen. Bei allen anderen Entity-Definitionen geben Sie keines dieser Schlüsselwörter an. Anschließend folgt, in Anführungszeichen gesetzt, der Wert, den Sie dem Entity-Namen zuweisen wollen. Der zugewiesene Wert kann je nach Typ des Entities ganz verschiedener Natur sein. Hinter dem Namen können in speziellen Fällen noch besondere Angaben folgen. Ein Beispiel dazu wird im Abschnitt Attribute mit Entity-Wert beschrieben. Jede Entity-Definition wird beendet mit einer schließenden spitzen Klammer >. Die einzelnen Teile der Entity-Definition werden durch ein oder mehrere Leerzeichen voneinander getrennt.
Eine solche Entity-Definition können Sie an irgendeiner Stelle innerhalb der DTD definieren – vor oder nach anderen Definitionen wie <!ELEMENT...> (Elemente), <!ATTLIST...> (Attribute) oder <!NOTATION...> (Notationen). In jedem Fall muss ein Entity jedoch vor seiner ersten Verwendung definiert werden. Dies ist z. B. bei Parameter Entities für DTD-Bausteine zu beachten, wo die Entity-Definitionen vor den Elementtyp-Definitionen notiert werden müssen, in denen sie verwendet werden. In der Praxis werden Entities meistens zu Beginn der DTD definiert, vor allen Element- und Attribut-Definitionen.
Entities für Textbausteine
Für längere Ausdrücke, die in den Anwendungsdaten einer XML-Struktur immer wieder vorkommen, wie etwa Eigennamen oder Floskeln, können Sie in der DTD Kürzel definieren.
<!ELEMENT text-mit-baustein (#PCDATA)>
<!ENTITY mfg "mit freundlichen Grüßen" >
Es gilt das Schema zur Definition von Entities. Bei Entities für Textbausteine brauchen Sie nur einen Namen für das Entity vergeben und einen gewünschten Wert zuordnen. Im Beispiel wird ein Entity mit Namen mfg
definiert, dem der Wert mit freundlichen Grüßen
zugeordnet wird.
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE text-mit-baustein SYSTEM "text-mit-baustein.dtd">
<text-mit-baustein>
ich verbleibe &mfg;
</text-mit-baustein>
Um ein in der DTD definiertes Entity in den Anwendungsdaten zu verwenden, notieren Sie ein kaufmännisches Und (&), direkt daran anschließend den Namen des Entities, und dahinter ein abschließendes Semikolon (;). Der XML-Parser setzt dann an der entsprechenden Stelle den Langtext ein, der zu dem Kürzel gehört. Das Beispiel &mfg;
erzeugt also die Ausgabe mit freundlichen Grüßen
.
Ein solches Entity können Sie innerhalb der Anwendungsdaten überall notieren, wo normale Zeichendaten möglich sind, also im Zeicheninhalt zwischen einem Anfangs- und einem End-Tag oder auch in Wertzuweisungen an Attribute, bei denen Zeichendaten erlaubt sind.
Netscape, Opera und Firefox beachten solche Entities nur in der internen DTD.
Entities für die Benennung von Zeichen
Aus HTML kennen Sie benannte Zeichen wie ü
oder ©
. Solche einfach zu merkenden Benennungen für Sonderzeichen können Sie in einer XML-DTD selbst definieren. Sinnvoll ist dies vor allem für Zeichen, die nicht auf der Tastatur zu finden sind, oder wenn Sie nicht wissen, mit welchen verschiedenen Entwicklungsumgebungen und internen Kodierungen die Anwender Ihrer XML-DTD arbeiten werden.
<!ENTITY sad_smiley "☹" >
<!ENTITY happy_smiley "☺" >
<!ELEMENT smilies (#PCDATA)>
Als Grafiken sehen die im Beispiel gewünschten Zeichen in etwa so aus:
sad_Smiley: ☹ und happy_Smiley: ☺
Es gilt das Schema zur Definition von Entities. Bei Entities für die Benennung von Zeichen brauchen Sie nur einen Namen für das Entity vergeben und als Wert die numerische Notation des Zeichens in dezimaler oder hexadezimaler Schreibweise zuordnen. Im Beispiel werden zwei Zeichen benannt. Die Namen lauten sad_smiley und happy_smiley. Im Unicode-System haben die beiden gewünschten Zeichen, die diesen Namen zugeordnet werden sollen, in hexadezimaler Schreibweise die Werte 2639 und 263A. Die Notationsweise ist dabei die gleiche wie in HTML 4.0, also z. B. ☺
(hexadezimal) oder ☺
(dezimal). Die Notation beginnt mit dem kaufmännischen Und &, gefolgt von einem Gatterzeichen #. Wenn Sie den Zeichenwert hexadezimal angeben wollen, muss ein x folgen und dahinter der hexadezimale Wert. Wenn Sie den Zeichenwert dezimal angeben wollen, folgt direkt die Zahl (ohne x davor). Hinter dem Zeichenwert folgt ein Semikolon ;.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE smilies SYSTEM "smilies.dtd">
<smilies>
bist du &happy_smiley; oder &sad_smiley;?
</smilies>
Um das benannte Zeichen in den Anwendungsdaten zu verwenden, notieren Sie ein kaufmännisches Und (&), direkt daran anschließend den Namen des Entities, und dahinter ein abschließendes Semikolon (;). Der XML-Parser setzt dann an der entsprechenden Stelle das zugehörige Zeichen ein. Im Beispiel erreichen Sie also durch die Notation von &happy_smiley; das Gleiche, was Sie mit ☺ erreichen würden – aber der Name ist eben leichter zu merken.
Die Notation ist innerhalb der Anwendungsdaten überall erlaubt, wo normale Zeichendaten möglich sind, also im Zeicheninhalt zwischen einem Anfangs- und einem End-Tag oder auch in Wertzuweisungen an Attribute, bei denen Zeichendaten erlaubt sind.
Netscape, Opera und Firefox beachten solche Entities nur in der internen DTD.
Verschachtelte Entities
Bei der Wertzuweisung in einer Entity-Definition können Sie durchaus auch andere Entities verwenden und auf diese Weise komplexe Bausteine erzeugen.
<!ENTITY f "Hatzelbutz und Partner GmbH" >
<!ENTITY m "info@example.org" >
<!ENTITY fm "&f;, &m;" >
<!ELEMENT mailtext (#PCDATA)>
In diesem Beispiel werden die zuvor definierten Entities f
und m
in der Wertzuweisung des Entities fm
verwendet.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE mailtext SYSTEM "mailtext.dtd">
<mailtext>
die Firma &f; freut sich, Ihnen ihre neuesten Produkte vorstellen
zu können. Schicken Sie Ihre Bestellung an &fm;.
</mailtext>
Wird in den Anwendungsdaten &fm;
notiert, so wird dies ersetzt durch Hatzelbutz und Partner GmbH, info@example.org
. Im XML-Fachjargon sagt man auch, die Einzelbausteine &f;
und &m;
werden "durchgereicht".
Entities für externe Ressourcen
Über Entities für externe Ressourcen, auch externe Entities genannt (im Gegensatz zu allen anderen Entity-Typen, die als interne Entities bezeichnet werden), stellt XML eine Möglichkeit bereit, einem Parser mitzuteilen, dass Daten aus einer anderen Datei eingebunden werden sollen.
<!ELEMENT news (newsdaten)*>
<!ENTITY datenquelle SYSTEM "news.txt" >
<!ELEMENT newsdaten EMPTY>
<!ATTLIST newsdaten
quelle ENTITY #REQUIRED
>
Es gilt das Schema zur Definition von Entities. Bei Entities für externe Ressourcen müssen Sie hinter dem Namen des Entities eines der beiden Schlüsselwörter SYSTEM oder PUBLIC (jeweils groß geschrieben) notieren. Wenn Sie die externe Datenquelle direkt mit ihrem Dateinamen bezeichnen, dann verwenden Sie SYSTEM. Bei der Wertzuordnung notieren Sie dann den Dateinamen der externen Quelle, gegebenenfalls mit absoluter oder relativer Pfadangabe. Es kann auch ein URI sein, z. B. http://www.example.org/news/news.txt
. Wenn Sie stattdessen eine öffentliche Quellenbezeichnung (public identifier) angeben, dann verwenden Sie PUBLIC und notieren bei der Wertzuordnung die öffentliche Quellenbezeichnung der Datenquelle.
Ein Entity für externe Ressourcen können Sie innerhalb der XML-Anwendung nur verwenden, indem Sie den Entity-Namen einem Attribut zuordnen. Das ist eine Besonderheit bei dieser Art von Entities. Deshalb müssen Sie in der DTD neben dem Entity auch für irgendeinen gewünschten Elementtyp ein Attribut mit Entity-Wert definieren. Im obigen Beispiel wird ein Elementtyp newsdaten
mit einem Attribut quelle
definiert, das durch die Angabe ENTITY als Attribut mit Entity-Wert festgelegt wird.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE news SYSTEM "news.dtd">
<news>
<newsdaten quelle="datenquelle" />
</news>
Dem Element newsdaten
wird beim Attribut quelle
der Entity-Name "datenquelle" zugewiesen. Dieser Name wird dann durch die damit verbundene Verknüpfung "news.txt" ersetzt. Der XML-Parser wird gleichzeitig darüber "informiert", dass es sich dabei nicht um eine Textersetzung handelt, sondern um die Angabe einer externen Referenz.
Beachten Sie:
Damit die externe Referenz an der entsprechenden Stelle eingefügt wird, muss der Parser diese Information natürlich verarbeiten können und einen Weg kennen, die entsprechenden Daten anzuzeigen. Besonders bei binären Datentypen, etwa bei Grafiken, sind zusätzliche Angaben bei der Definition erforderlich. Ein Beispiel dafür finden Sie im Abschnitt Attribute mit Entity-Wert.
XML schreibt bei lokalen Pfadnamen (SYSTEM) nicht vor, wie die Syntax lautet. Wird ein Windows-PC verwendet, kann es durchaus nötig sein, bei Pfadnamen Backslashes \ statt der Unix-typischen Slashes / zu verwenden. Ebenso hängt es vom verarbeitenden Parser ab, ob er angegebene URIs auflösen kann oder nicht.
Ein Beispiel für die Verwendung einer öffentlichen Bezeichnung (public identifier) wäre etwa:
<!ENTITY % HTML_Chars PUBLIC "-//W3C//ENTITIES Latin1//EN//HTML" >
%HTML_Chars;
Mit einer solchen Definition binden Sie die benannten Zeichen aus HTML in Ihre DTD ein. Genauere Beschreibungen zum Einbinden externer Ressourcen in eine DTD finden Sie im Abschnitt Modulare DTDs mit Hilfe von Entities.
Einige Parser meckern bei Beispielen wie dem obigen, obwohl diese XML-konform sind.
Parameter Entities für komplexere DTDs
Parameter Entities erlauben, "Makros" für die Verwendung innerhalb der DTD zu definieren. Besonders sinnvoll ist ihr Einsatz, wenn bestimmte komplexere Angaben zum Inhalt von Elementtypen bei mehreren Elementtypen wiederkehren. So kann man beispielsweise innerhalb eines Textes Formatierungen wie fett, kursiv, farbig, unterstrichen usw. zu einem Makro "Textformatierung" zusammenfassen. Definiert man nun bedeutungstragende Text-Elemente wie Überschriften, Listeneinträge oder Tabellenzellen, so wäre es unnötige Kopierarbeit, jedem dieser Text-Elemente wieder alle Formatierungsmöglichkeiten zuzuweisen. Einfacher ist es, nur noch das Makro "Textformatierung" zuzuweisen. Parameter Entities erhöhen somit in komplexen DTDs die Lesbarkeit und die Änderungsfreundlichkeit.
<!ENTITY % artikel "artikelnummer, artikelname, artikelmenge">
<!ENTITY % zusatz "beschreibung | warenklasse">
<!ELEMENT lager (eingang | ausgang)*>
<!ELEMENT eingang (eingangsnummer, (%artikel;), (%zusatz;))>
<!ELEMENT ausgang (ausgangsnummer, (%artikel;), (%zusatz;))>
<!ELEMENT eingangsnummer (#PCDATA)>
<!ELEMENT ausgangsnummer (#PCDATA)>
<!ELEMENT artikelnummer (#PCDATA)>
<!ELEMENT artikelname (#PCDATA)>
<!ELEMENT artikelmenge (#PCDATA)>
<!ELEMENT beschreibung (#PCDATA)>
<!ELEMENT warenklasse (#PCDATA)>
Das Beispiel stellt einen Auszug aus einer DTD zu einer Datei dar, in der Lagervorgänge festgehalten werden. In dem Lager gibt es Wareneingänge und Warenausgänge. In jedem Datensatz soll ein Wareneingang oder der Warenausgang eines bestimmten Warenartikels festgehalten werden. Ein Artikel im Zusammenhang mit Wareneingang oder Warenausgang setzt sich immer wieder aus den gleichen Daten zusammen: aus Artikelnummer, Artikelname, Artikelmenge und einem beschreibenden Zusatz, der entweder eine allgemeine Artikelbeschreibung ist oder die Einordnung in eine Warenklasse. Solche zusammengehörigen Daten lassen sich bei Elementtyp-Definitionen zu Parameter Entities zusammenfassen.
Im Beispiel werden zwei Parameter Entities definiert: artikel
und zusatz
. Dabei gilt das Schema zur Definition von Entities. Vor dem Namen eines Parameter Entities notieren Sie ein Prozentzeichen %. Bei der Wertzuordnung notieren Sie eine Angabe zum Inhalt eines Elementtyps. Es handelt sich jedoch nicht wirklich um die Angabe zu einem Elementtyp-Inhalt, sondern einfach um ein Textbaustein, ein Makro, das Sie in nachfolgenden Elementtyp-Definitionen verwenden können. In beiden Parameter Entities des obigen Beispiels werden Angaben für Elementinhalte definiert.
Im Beispiel werden die Parameter Entities bei der Definition der Elementtypen eingang
und ausgang
verwendet. Beide Elementtypen haben Elementinhalt. Sie bestehen aus einer Laufnummer für den Eingang bzw. Ausgang, der Artikelnummer und dem Artikelname, zusammengefasst in der Verwendung des Parameter Entity artikel
, und wahlweise aus einer Artikelbeschreibung oder der Angabe einer Warenklasse, zusammengefasst in der Verwendung der Parameter Entity zusatz
.
Bei der Verwendung eines Parameter Entity in einer Elementtyp-Definition müssen Sie auf die Notation wie im Beispiel angegeben achten. Parameter Entities müssen in Klammern gesetzt werden. Unmittelbar vor dem Namen des Parameter Entity (ohne Leerzeichen dazwischen) muss das Prozentzeichen % stehen. Hinter dem Namen muss ein Strichpunkt ; notiert werden.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE lager SYSTEM "lager.dtd">
<lager>
<eingang>
<eingangsnummer>452</eingangsnummer>
<artikelnummer>45-234</artikelnummer>
<artikelname>Schreibtischstuhl "Chef"</artikelname>
<artikelmenge>10</artikelmenge>
<warenklasse>C-III</warenklasse>
</eingang>
<ausgang>
<ausgangsnummer>318</ausgangsnummer>
<artikelnummer>37-917</artikelnummer>
<artikelname>Spiegelschrank "Narziss"</artikelname>
<artikelmenge>3</artikelmenge>
<beschreibung>F-IV</beschreibung>
</ausgang>
</lager>
Dem Anwendungsbeispiel ist nicht mehr zu entnehmen, dass die Definition der Elementtypen eingang
und ausgang
zum Teil auf Verwendung von Parameter Entities beruht. Parameter Entities sind also nur innerhalb der DTD-Definitionen von Bedeutung, auf die Anwendung haben sie keinen Einfluss. Das Beispiel der angewendeten DTD-Definitionen zeigt zwei Datensätze, je einen für einen Wareneingang und einen für einen Warenausgang. Die inneren Elemente sind dabei so notiert, wie es die definierten Regeln zulassen.
Modulare DTDs mit Hilfe von Entities
Beim Entwurf komplexer Datenstrukturen macht es häufig Sinn, die Definitionen auf mehrere DTDs zu verteilen. Mit Hilfe von Entities können Sie DTDs in andere DTDs als Module importieren. So bietet es sich beispielsweise in einem betriebswirtschaftlichen Datensystem an, eine separate DTD mit den Datenstrukturen eines Produkts anzulegen, die dann in verschiedenen anderen Datenstrukturen, etwa denen für eine Produktbestellung oder der für die Produktbestandsverwaltung im Lager, importiert werden kann.
<!ELEMENT produkt (warennummer,bezeichnung,hersteller)>
<!ELEMENT warennummer (#PCDATA)>
<!ELEMENT bezeichnung (#PCDATA)>
<!ELEMENT hersteller (#PCDATA)>
<!ENTITY % produktdaten SYSTEM "produkt.dtd" >
%produktdaten;
<!ELEMENT bestellungen (bestellung)*>
<!ELEMENT bestellung (produkt,besteller,anzahl,preis)*>
<!ELEMENT besteller (#PCDATA)>
<!ELEMENT anzahl (#PCDATA)>
<!ELEMENT preis (#PCDATA)>
In der DTD mit Namen produkt.dtd
wird ein Elementtyp produkt
mit Elementinhalt definiert. Der Elementinhalt besteht aus den Elementtypen warennummer, bezeichnung
und hersteller
, die jeweils Zeicheninhalt haben können.
In der zweiten DTD mit Namen bestellung.dtd
wird die DTD für Produktdaten nun eingebunden. Dazu wird zunächst ein Entity für externe Ressourcen mit Namen produktdaten
definiert. Es verweist auf die andere DTD produkte.dtd
. Wichtig ist dabei aber die Notation des Prozentzeichens vor dem Entity-Namen, so wie es bei Parameter Entities für DTD-Bausteine üblich ist. Denn durch das Prozentzeichen geben Sie an, dass Sie das Entity innerhalb der aktuellen DTD verwenden wollen, und dass dessen Inhalt als Bestandteil der DTD zu interpretieren ist.
Das so definierte Entity wird anschließend außerhalb jeder anderen DTD-Definition alleinstehend notiert (%produktdaten;). Dadurch werden die Definitionen aus produkt.dtd
an dieser Stelle eingebunden und können in nachfolgenden Definitionen verwendet werden. Im obigen Beispiel können Sie das an der Definition des Elementtyps bestellung
sehen. Dieser Elementtyp enthält als Elementinhalt vier Elementtypen. Davon werden aber nur drei in der aktuellen DTD definiert, nämlich besteller, anzahl
und preis
. Der andere Elementtyp produkt
ist derjenige, der in produkt.dtd
definiert ist.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE bestellungen SYSTEM "bestellungen.dtd">
<bestellungen>
<bestellung>
<produkt>
<warennummer>39304</warennummer>
<bezeichnung>Bohrmaschine XPL75</bezeichnung>
<hersteller>Schniedelwutz & Söhne</hersteller>
</produkt>
<besteller>Raffmarkt, Niederlassung Hamburg</besteller>
<anzahl>100</anzahl>
<preis>45900,00</preis>
</bestellung>
<bestellung>
<produkt>
<warennummer>92842</warennummer>
<bezeichnung>Badehaube Paris</bezeichnung>
<hersteller>Etienne Monet</hersteller>
</produkt>
<besteller>Sandburg Bademoden, Berlin</besteller>
<anzahl>10</anzahl>
<preis>234,00</preis>
</bestellung>
</bestellungen>
In einer Anwendungsdatei wird lediglich die bestellungen.dtd
angegeben. Trotzdem ist auch die produkt.dtd
relevant, da sie in die bestellungen.dtd
eingebunden wurde. Denn an der Stelle, der bestellungen.dtd
, an der dem Elementtyp bestellung
der Elementinhalt produkt
zugewiesen wird, ist ja die komplette Definition des Elementtyps produkt
aus der produkt.dtd
gemeint.