www.stefanheymann.de

Stefan Heymann

Home | Fotografie · Hasselblad · Galerie | Ruler · XML · HomePump · HomeGallery

DTD – Document Type Definition

Dieses Dokument versucht, einen Schnelleinstieg in die DTDs von XML zu bieten. Es werden daher nur die – meiner Meinung nach – wichtigsten Aspekte von DTDs behandelt. Genaue Auskunft gibt allein die englische Originalfassung der XML-Spezifikation.


Inhalt


DTD – was ist das?

Der XML-Standard definiert selbst keine Elemente ("Tags") oder Entities. Für den Austausch von XML-Dokumenten ist es aber wichtig, dass beide Seiten (Ersteller und Verarbeiter; Lieferant und Kunde) sich an die selben Konventionen in Bezug auf die verwendeten Elemente (Tags), Entities und auch die Struktur des Dokuments halten.

Diese Konventionen werden in der Document Type Definition (=DTD) festgelegt. Spezielle "Validating Parser" sind in der Lage, zu überprüfen, ob ein bestimmtes Dokument sich an seine DTD hält.

Anders gesagt, macht erst eine DTD eine spezielle XML-Anwendung aus. Sie definiert, welche Elemente es gibt und wie diese im Dokument angeordnet werden (müssen).

Deklaration

Eine DTD wird am Anfang eines XML-Dokuments in der sog. Document Type Declaration untergebracht. Die DTD-Definitionen bestehen selbst aus speziellem Markup. Eine DTD kann außerhalb des Dokuments liegen. Alternativ oder zusätzlich dazu können weitere DTD-Deklarationen im XML-Dokument stehen.

Externe und interne Definitionen:

	<!DOCTYPE name SYSTEM "externe.dtd"
	 [ ... Deklarationen der internen DTD ... ]>

Mit PUBLIC-Identifier:

	<!DOCTYPE name PUBLIC "publicid" "externe.dtd"
	 [ ... Deklarationen der internen DTD ... ]>

Nur externe Definitionen

	<!DOCTYPE name SYSTEM "externe.dtd">

Nur interne Definitionen:

	<!DOCTYPE name [ ... Deklarationen der internen DTD ...
]>

Die DTD-Deklaration steht am Anfang des Dokuments, nach der XML-Deklaration (<?xml ... ?>, falls überhaupt vorhanden) und vor dem eigentlichen Inhalt.

Die DTD-Deklaration kann beliebige Kommentare und Processing Instructions (PIs) enthalten.

Externe DTDs

Der externe Teil kann über das Schlüsselwort SYSTEM direkt in einer URL angegeben werden (z. B. SYSTEM "http://dtdserver/orderapp/orderapp.dtd").

Alternativ kann über das Schlüsselwort PUBLIC auch eine "öffentliche" DTD angesprochen werden. Es wird dabei davon ausgegangen, dass der jeweilige Parser die öffentliche DTD "kennt" bzw. eingebaut hat und ihm daher die Angabe des Namens der öffentlichen DTD reicht (z. B. PUBLIC "//heymann-net.de/orderapp/orderapp.1.0.0.dtd"). Die Benennung der PUBLIC-Namen ist nicht genormt.

Es können auch Mischformen angegeben werden (PUBLIC und SYSTEM, wobei das Schlüsselwort SYSTEM dann entfällt):

	PUBLIC "//heymann-net.de/orderapp/orderapp.1.0.0.dtd"  "orderapp.dtd"

Externe DTDs sollen mit einer Text-Deklaration beginnen. Diese Unterscheidet sich vom XML-Prolog dadurch, dass die "Standalone"-Angabe fehlt.

DTD-Name

Der Name der DTD steht auch für die Anwendung, für die die DTD entwickelt wird. Er entspricht dem Element-Typ, der das ganze Dokument umschließt. Wird also z. B. eine DTD deklariert mit

	<!DOCTYPE orderapp SYSTEM "orderapp.dtd">

wird das gesamte Dokument von einem "orderapp"-Element umschlossen.

Interne DTDs

Der interne Teil der DTD (also der Teil, der sich direkt im Dokument befindet) steht in eckigen Klammern. Er ist optional. Deklarationen, die hier gemacht werden, überschreiben bzw. ergänzen die Deklarationen der externen DTD.


Bausteine der DTD

Eine DTD beschreibt folgende Dinge:


Elemente

Allgemeine Form:

	<!ELEMENT name inhalt >

Für "inhalt" kann angegeben werden:

EMPTY Das Element ist immer leer (z. B. Zeilenumbruch BR)
ANY Es kann jeder beliebige Inhalt (Text, weitere Elemente) enthalten sein
(#PCDATA) Es kann lediglich Text enthalten sein
(#PCDATA | el1 | el2 | ...)* Text, gemischt mit den angegebenen Elementen. Dies könnten z. B. Elemente zur Zeichenformatierung sein (b, i, usw.)
(el1 | el2, el3, el4* | el5+ | el6?, el7) Angabe der möglichen Elemente (getrennt durch |-Symbol) oder der genauen Reihenfolge (getrennt durch Komma). Zusammenfassen durch runde Klammern ist erlaubt. Die Sonderzeichen nach den Elementnamen sind:
Keines  Element kommt genau einmal vor
+ Element kommt mindestens einmal vor
* Element kommt gar nicht oder beliebig oft vor
? Element kommt gar nicht oder genau einmal vor

Beispiele:

EMPTY: immer leer

	<!ELEMENT BR EMPTY>

ANY: Absatz: Beliebige Elemente in beliebiger Reihenfolge und Schachtelung

	<!ELEMENT absatz ANY>

PCDATA: Überschrift: Darf nur Text enthalten

	<!ELEMENT header (#PCDATA) >

Mischungen:

	<!ELEMENT p (#PCDATA | b | i )* >
	<!ELEMENT kunde (name, adresszeile+, bonitaet) >

Attribute

Hier kann zu jedem Element definiert werden, welche Attribute (Attribut-Namen) es enthalten kann und welche Default-Werte für diese Attribute angenommen werden, wenn sie nicht angegeben sind.

Allgemein:

	<!ATTLIST elementname
	          name typ default       (Diese Zeile beliebig oft)
          >     

Beispiel:

	<!ATTLIST absatz
	          valign       (top | center | bottom)          'top'
	          halign       (left | center | right | block)  'left'
	          bordertop    NMTOKEN                          '0'
	          borderleft   NMTOKEN                          '0'
	          borderright  NMTOKEN                          '0'
	          borderbottom NMTOKEN                          '0' >

Hier werden die für das Element "absatz" möglichen Attribute (valign, halign, bordertop, usw.) und ihre Default-Werte definiert.

Typen:

Typ Inhalt Beispiel
CDATA Beliebiger Text ("Character Data") Alle meine Entchen
ID Ein XML-Bezeichner (muss mit Buchstabe, Unterstrich oder Doppelpunkt beginnen). Ein ID-Wert ist eindeutig, darf also in einem XML-Dokument nur genau einmal in diesem Attribut vorkommen. A102823
IDREF Ein Bezug auf eine im Dokument vorhandene ID. Solche Bezüge dürfen natürlich öfter vorkommen. A102
IDREFS Mehrere, durch Leerschritte getrennte IDREF-Bezeichner A102 A103
ENTITY Name einer in der DTD definierten Unparsed Entity gif
ENTITIES Mehrere, durch Leerschritte getrennte, Uparsed Entity-Namen gif jpeg png
NMTOKEN Ein Namens-Token. Erlaubte Zeichen: A..Z, a..z, 0..9, Punkt, Bindestrich, Underscore, Doppelpunkt, Mittelpunkt (#183) 10P-3
NMTOKENS Mehrere durch Leerschritte getrennte NMTOKEN 1 2 3 4 5
(enumeration) Enumeration: Durch |-Symbole getrennte NMTOKEN, in runde Klammern gesetzt (left | right)
NOTATION Notations-Attribut: Durch |-Symbole getrennte Aufzählung von in der DTD deklarierten Notations-Namen. Diese Notationen werden benutzt, um den Inhalt des Elements zu interpretieren. NOTATION (gif | jpeg | png)

Angabe des Defaults:

Angabe Bedeutung Wenn das Attribut im Start-Tag fehlt, Beispiel
'defaultwert' Direkte Angabe eines Default-Werts wird der Default-Wert angenommen

colorname CDATA 'blau'
xml:space (default|preserve) "preserve"

#REQUIRED Das Attribut muss auf jeden Fall explizit angegeben werden liegt ein Fehler vor

xpos CDATA #REQUIRED

#IMPLIED Der Default-Wert wird von der Anwendung eingesetzt weiß die Anwendung schon, was sie dann macht

MwSt CDATA #IMPLIED

#FIXED 'defaultwert' Es darf nur der angegebene Wert als Attribut-Wert angegeben werden wird der Default-angenommen. Wenn ein anderer Wert angegeben ist, liegt ein Fehler vor.

tyres CDATA #FIXED '4'


Entities

Entities sind Textbausteine, die vom einzelnen Zeichen bis zum kompletten externen XML-Dokument reichen können. Der Aufruf geschieht durch &entityname; im Dokument. Entity-Inhalte werden in der DTD deklariert. Entities können ihrerseits wieder Entity-Aufrufe (-Referenzen) enthalten.

Allgemein:

	<!ENTITY name "inhalt" >
	<!ENTITY name SYSTEM "extern.xml" >
	<!ENTITY name SYSTEM "image.gif" NDATA gif>

Beispiele:

	<!ENTITY versionsnummer '1.0.1' >
	<!ENTITY datum "2000-01-27" >
	<!ENTITY build "1023" >
	<!ENTITY einleitung SYSTEM "./einleitung.xml" >
	<!ENTITY versionskennung "&versionsnummer; &datum; &build;" >
                              <!-- Entity mit enthaltenen Entities -->

Parameter-Entities

Parameter-Entities sind ein Sonderfall der Entities. Es handelt sich dabei um spezielle Entities, die nur innerhalb der DTD referenziert (aufgerufen) werden dürfen. Dadurch können DTD-Teile deklariert werden, die an mehreren Stellen verwendet werden können. Es können dabei keine Namenskonflikte mit General-Entities auftreten, denn Parameter-Entities werden immer durch ein Prozent-Zeichen eingeleitet.

Allgemein:

	<!ENTITY % name inhalt >
	(Der Leerschritt zwischen %-Zeichen und
	Name ist hier zwingend erforderlich)

Beispiel:

	<!ENTITY % generalattributes "id ID #IMPLIED" >

Aufruf-Beispiel:

	<!ATTRLIST para
	           h-align (left | center | right | block) 'left'
	           %generalattributes >
	(Hier darf kein Leerzeichen zwischen %-Zeichen und Name stehen)

Entity-Schachtelung

Das Einschachteln der verschiedenen Entities soll hier anhand des Beispiels aus der XML-Spezifikation gezeigt werden:

Deklarationen in der DTD:

	<!ENTITY % pub    "&#xc9;ditions Gallimard" >
	<!ENTITY   rights "All rights reserved" >
	<!ENTITY   book   "La Peste: Albert Camus,
			   &#xA9; 1947 %pub;. &rights;" >

Aufruf von &book; im Dokument ergibt dann den Text:

	La Peste: Albert Camus,
	© 1947 Éditions Gallimard. All rights reserved

Parsed/Unparsed Entities

Entities werden unterschieden in

Unparsed Entities bekommen immer eine Notation zugewiesen. Diese hilft der XML-Anwendung, den passenden Prozessor für die jeweilige Notation (=Art von Unparsed Entity) zu finden.

Bei jeder Deklaration einer Unparsed Entity wird über das Schlüsselwort NDATA die – vorher deklarierte – Notation angegeben:

Deklaration einer externen unparsed Entity des Typs "gif:

	<!ENTITY name SYSTEM "image.gif" NDATA gif>

Notationen

Deklaration:

	<!NOTATION name SYSTEM "system-bezeichner" >
	<!NOTATION name PUBLIC "public-bezeichner" "system-identifier" >
	<!NOTATION name PUBLIC "public-bezeichner" >

Notationen werden eingesetzt für

Conditional Sections

In einer externen DTD können Abschnitte über Conditional Sections beliebig ein- und ausgeblendet werden:

	<![ INCLUDE [ DTD-Deklarationen ]]>
	<![ IGNORE  [ DTD-Deklarationen ]]>

Die DTD-Deklarationen innerhalb der eckigen Klammern müssen komplett sein, auch bei IGNORE-Abschnitten, damit das Ende vom Parser korrekt erkannt werden kann.

Conditional Sections können geschachtelt sein. INCLUDE-Anweisungen innerhalb von IGNORE-Teilen werden aber trotzdem ignoriert.

Die Schlüsselwörter "INCLUDE" und "IGNORE" können auch als Parameter-Entity deklariert werden. Dadurch können z. B. verschiedene Fassungen (Entwurf, Endgültige fassung) eines Dokuments einfach unterschieden werden, indem bestimmten Parameter-Entities die Bedeutung "INCLUDE" oder "IGNORE" zugewiesen wird.


Stefan Heymann

Letzte Änderung: 2003-01-03