In einer Document Type Definition (DTD) werden alle Elemente und deren Attribute definiert, die in einem XML-Dokument gültig sind. Eine DTD kann innerhalb des XML-Dokuments angegeben werden, oder als externe Referenz eingebunden werden. Mithilfe einer DTD können verschiedene XML-Dokumente erstellt werden, die einer gemeinsamen Struktur entsprechen.
XML-Parser verwenden die DTD um die Struktur eines XML-Dokuments zu prüfen, bevor das Dokument verarbeitet wird. So kann sichergestellt werden, dass nur strukturell korrekte Daten eingelesen werden.
Der Inhalt eines XML-Dokuments setzt sich aus folgenden Teilen zusammen:
- Elemente
- Attribute
- Entity references
- PCDATA
- CDATA
Folglich müssen in einer DTD all diese Teile spezifiziert werden können.
Elemente
In einer DTD werden Element durch folgende Syntax spezifiziert:
<!ELEMENT name kategorie>
oder
<!ELEMENT name (inhalt)>
Die Angabe name entspricht dem Namen des Elements.
Element-Kategorien
Mit der ersten Syntax kann ein Element einer bestimmten Kategorie zugeordnet werden. Die Kategorie bezieht sich auf die Inhaltstexte des Elements und kann folgende Werte haben:
EMPTY |
Das Element darf keinerlei Inhalt enthalten. Weder Kindelemente, PCDATA oder CDATA-Sektionen sind erlaubt. Es handelt sich somit um ein leeres Element. |
ANY |
Das Element darf alle Kombinationen von Inhalten enthalten. Sowohl Kindelemente, PCDATA oder CDATA-Sektionen sind erlaubt. |
Sequenz von Kindelementen
Mit der zweiten Syntax können die erlaubten Inhalte eines Elements genauer festgelegt werden, als durch die Angabe von EMPTY und ANY. Innerhalb der Klammern können anstelle von inhalt, verschiedene Werte angegeben werden, die im Folgenden erläutert werden.
Durch Kommas getrennt, können innerhalb der Klammern die Namen der Kindelemente definiert werden, die in dem Element erlaubt sind. Gleichzeitig wird auch die Reihenfolge bestimmt, in der die Kindelemente angegeben werden müssen.
<!ELEMENT anschrift (strasse, plz, ort)>
Zusätzlich kann bei jedem Kindelement angegeben werden, wie häufig es vorkommen darf. An den Namen des Kindelements wird für die Definition der Häufigkeit entweder ein Plus + , ein Stern * oder ein Fragezeichen ? angehängt. Wird keines der Zeichen angehängt, so muss das Kindelement exakt einmal vorkommen.
+ |
Das Kindelement muss mindestens einmal vorkommen. |
* |
Das Kindelement kann beliebig oft vorkommen (kein Vorkommen eingeschlossen). |
? |
Das Kindelement muss exakt einmal vorkommen oder gar nicht. |
<!ELEMENT telefonnummer (vorwahl?, nummer)>
Gibt es zu einem Kindelement oder einer Gruppe von Kindelementen eine Alternative, so kann durch Angabe eines senkrechten Strichs | eine Oder-Bedingung festgelegt werden. Gruppen von Kindelementen können durch Klammerung mit runden Klammern gebildet werden.
<!ELEMENT adresse (vorname, nachname, (anschrift|postfach))> <!ELEMENT kontakt (adresse|telefonnummer|email)>
#PCDATA
Wird als Inhalt #PCDATA definiert, so darf das Element jede Art von Text enthalten, aber keine Kindelemente.
<!ELEMENT vorname (#PCDATA)>
Es können aber auch Mischformen definiert werden. So erlaubt folgende Definition sowohl die Angabe von Textinhalten, wie auch die Angabe bestimmter Kindelemente:
<!ELEMENT vorwahl (#PCDATA|(landesvorwahl, ortsvorwahl))>
Attribute
Attribute werden durch folgende Syntax spezifiziert:
<!ATTLIST element name typ vorgabewert>
Die Angabe element entspricht dem Namen des Elements, für das das Attribut definiert wird. Die Angabe name ist entsprechend der Name des Attributs. Unter der Angabe typ wird der Typ des Attributwertes angegeben.
Der Typ kann mit folgenden Schlüsselworten festgelegt werden:
CDATA |
Der Wert ist ein beliebiger Text. |
ID |
Der Wert muss im gesamten XML-Dokument eingeutig sein, unabhängig davon, in welchem Element oder Attribut vom Typ ID der Wert angegeben ist. |
IDREF |
Der Wert ist eine Referenz auf einen ID-Wert eines Attributs vom Typ ID. |
IDREFS |
Der Wert ist eine Liste von Referenzen auf ID-Werte. |
NMTOKEN |
Der Wert ist ein gültiger XML-Bezeichner, d.h. er entspricht den Namenskonventionen für Elemente. |
NMTOKENS |
Der Wert ist eine Liste von NMTOKEN. |
ENTITY |
Der Wert ist eine Entity reference. |
ENTITIES |
Der Wert ist eine Liste von Entity references. |
NOTATION |
Der Wert ist der Name einer Notation. |
xml: |
Der Wert ist ein vordefinierter XML Wert. |
Es ist auch möglich anstatt der oben genannten Schlüsselworte, innerhalb runder Klammern eine Aufzählung von erlaubten Werten anzugeben. Die einzelnen Werte werden durch einen senkrechten Strich voneinander getrennt.
<!ATTLIST zahlungsweise typ (ec-karte|kreditkarte|nachnahme)>>
Die Angabe vorgabewert ist optional und legt fest, ob ein Attribut angegeben werden muss, oder falls es nicht angegeben werden muss, welchen Vorgabewert es haben soll. Folgende Werte sind möglich:
Wert |
Der Vorgabewert des Attributs, falls es nicht angegeben wurde. |
#REQUIRED |
Das Attribut muss angegeben werden. |
#IMPLIED |
Das Attribut kann angegeben werden und hat, falls nicht angegeben, keinen Wert. |
#FIXED wert |
Der mit der Angabe wert definierte Wert des Attributs kann nicht überschrieben werden. |
<!ATTLIST zahlungsweise typ (ec-karte|kreditkarte|nachnahme) "kreditkarte">
<!ATTLIST rechnung anschrift (name|strasse|plz|ort) #REQUIRED>
Entitäten (Entity)
XML Sicherheit
Mit Entitäten ist es möglich, einen Speicherüberlauf zu erzeugen und damit eine ganze Anwendung zum Absturz zu bringen. Man stelle sich hierzu folgendes XML-Dokument vor:
<?xml version="1.0"?> <!DOCTYPE demo [ <!ENTITY a "&b;&b;&b;"> <!ENTITY b "&c;&c;&c;"> <!ENTITY c "&d;&d;&d;"> <!ENTITY d "0000000000"> ]> <demo> &a; </demo>
Ein XML-Parser erzeugt daraus folgendes im Speicher:
<demo> 0000000000…0000000000 </demo>
Die Entität &a; wird in eine Folge von 10 * 3↑3 Nullen aufgelöst. Erhöht man nun entsprechend die Anzahl der verschachtelten Entitäten und definiert statt 10 Nullen, 1000 Nullen, gelangt man schnell an die Speichergrenzen des Systems.
Um solche Angriffe zu verhindern, kann man bei einigen XML-Parsern die Verschachtelungstiefe von Entitäten beschränken.
Eine Entity ist eine Variable, dessen Wert während des Einlesens des XML-Dokuments vom XML-Parser die entsprechende Entity reference im XML-Dokument ersetzt. Eine Entity wird wie folgt spezifiziert:
<!ENTITY name "wert">
Dazu folgendes Beispiel:
<!ENTITY projektname "Projekt ABC">
Im XML-Dokument wird während des Einlesens der Ausdruck
<projekt><name>&projektname;</name></projekt>
zu folgendem Ausdruck vervollständigt:
<projekt><name>Projekt ABC</name></projekt>
Zu beachten ist, daß der Name des Platzhalters — der Entität im XML-Dokument — mit einem & (kaufm. Und) beginnen und mit einem ; (Semikolon) enden muß, damit der XML-Parser eine Entität erkennt und entsprechend ersetzt.
Einbinden einer DTD in ein XML-Dokument
Es gibt zwei Möglichkeiten eine DTD in ein XML-Dokument einzubinden. Entweder direkt in dem Dokument, oder als externe Referenz. Eine DTD wird grundsätzlich immer mittels einer DOCTYPE-Definition in ein XML-Dokument eingebunden. Lediglich der Aufbau der DOCTYPE-Definition ist bei einer direkten Einbindung unterschiedlich zur externen Referenz.
Direkte Einbindung
Eine DTD kann mit folgender DOCTYPE-Definition direkt in ein XML-Dokument eingebunden werden:
<!DOCTYPE wurzelelement dtd-deklarationen>
Die Angabe wurzelelement ist der Name des Wurzelelements. Die DTD-Deklarationen ELEMENT, ATTLIST und ENTITY werden innerhalb der eckigen Klammern angegeben.
<?xml version="1.0"?> <!DOCTYPE bestellung [ <!ELEMENT bestellung (zahlungsweise, betrag, mehrwertsteuer)> <!ELEMENT zahlungsweise EMPTY> <!ATTLIST zahlungsweise typ (ec-karte|kreditkarte|nachnahme) "kreditkarte"> <!ELEMENT betrag (#PCDATA)> <!ATTLIST betrag waehrung (euro|dollar)> <!ELEMENT mehrwertsteuer (#PCDATA)> <!ENTITY normalsatz "19"> ]> <bestellung> <zahlungsweise typ="nachnahme"/> <betrag waehrung="euro">120.99</betrag> <mehrwertsteuer>&normalsatz;</mehrwertsteuer> </bestellung>
Einbindung als externe Referenz
Mit folgender DOCTYPE-Definition wird eine DTD als externe Referenz eingebunden:
<!DOCTYPE wurzelelement PUBLIC "public-identifier" "system-identifier">
Das wurzelelement ist der Name des Wurzelelements des XML-Dokuments (z.B. html). Die Variable public-identifier ist der Name einer DTD, der in Form einer URI angegeben wird. Für einige DTDs gibt es standardisierte Namen, wie zum Beispiel -//W3C//DTD XHTML 1.0 Transitional//EN.
Ein system-identifier ist ein URI auf die eigentliche DTD, die entweder lokal auf dem System vorliegt, oder über das Netz, in Form einer URL erreicht werden kann. In der Regel verweigert ein XML-Parser die Verarbeitung des XML-Dokuments, wenn die DTD nicht geladen werden kann.
Alternativ kann statt der Angabe eines public-identifier mit folgender Syntax nur ein system-identifier angegeben werden:
<!DOCTYPE wurzelelement SYSTEM "system-identifier">
Beispiele
<!DOCTYPE bestellung SYSTEM "http://www.bitworld.de/bestellung.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Parameter Entity References
Neben den Entitäten, die bestimmte Platzhalter in dem XML-Dokument ersetzen, gibt es noch eine zweite Form von Entitäten, die Platzhalter innerhalb einer DTD ersetzen, die sogenannten Parameter Entity References. Eine Parameter Entity Reference wird mit folgender Syntax in der DTD definiert:
<!ENTITY % name "wert">
Der Unterschied ist das Prozentzeichen vor dem Namen der Entität. Auch der Platzhalter innerhalb der DTD wird anstatt des Kaufmännischen-Unds mit einem Prozentzeichen deklariert.
<?xml version="1.0"?> <!DOCTYPE bestellung [ <!ENTITY % adresse "strasse, plz, ort"> <!ELEMENT anschrift (name, %adresse;)> <!ELEMENT strasse (#PCDATA)> <!ELEMENT plz (#PCDATA)> <!ELEMENT ort (#PCDATA)> ]>
Der XML-Parser interpretiert diese DTD dann folgendermaßen:
<?xml version="1.0"?> <!DOCTYPE bestellung [ <!ELEMENT anschrift (name, strasse, plz, ort)> <!ELEMENT name (#PCDATA)> <!ELEMENT strasse (#PCDATA)> <!ELEMENT plz (#PCDATA)> <!ELEMENT ort (#PCDATA)> ]>
Einbindung externer Parameter Entity References
Mit Parameter Entity References ist es möglich, sich eine Bibliothek von Standard-Elementen zu definieren und diese in eine bestehende DTD zu integrieren. Auf diese Weise müssen komplexe Elemente nur einmal definiert werden. So können auch Kataloge von Entitäten zusammengestellt werden.
Eine Referenz auf eine externe DTD kann mit folgender Syntax erstellt werden:
<!ENTITY % name PUBLIC "public-identifier" "system-identifier">
oder
<!ENTITY % name SYSTEM "system-identifier">
Auch bei der Einbindung von externen DTDs wird das Prozentzeichen verwendet und der Name für den Platzhalter definiert. Allerdings müssen, wie bei der Einbindung von DTDs als externe Referenz in ein XML-Dokument, ein public-identifier und ein system-identifier angegeben werden oder optional nur ein system-identifier, wenn anstelle von PUBLIC das Schlüsselwort SYSTEM verwendet wird.
<!ENTITY % HTMLlat1 PUBLIC "-//W3C//ENTITIES Latin1//EN//HTML" "http://www.w3.org/DTD/ISOlat1.ent">
<!ENTITY % anschrift SYSTEM "http://www.bitworld.de/anschrift.dtd">
Eingebunden wird die externe DTD an der Stelle, an der der Platzhalter in der bestehenden DTD angegeben wird.
<?xml version="1.0"?> <!DOCTYPE bestellung [ <!ENTITY % anschrift SYSTEM "http://www.bitworld.de/anschrift.dtd"> %anschrift; <!ELEMENT anschrift (name, strasse, plz, ort)> <!ELEMENT name (#PCDATA)> ]>
Quellen
Extensible Markup Language (XML) 1.1 (Second Edition), W3C Recommendation, 16 August 2006
XMLidP XML Verständlich, Henning Behme, Stefan Mintert

![Validate my RSS feed [Valid RSS]](/templates/bitworld/images/valid-rss.png)
