Grundlegender Aufbau
DTDs sind in SGML definiert, aber nicht in XML.
Überwiegend werden <!-Tags verwendet, Elemente
mit !ELEMENT, Attribute mit !ATTLIST elementname
(in einer XML- Umgebung wäre es logischer, die Attribute
als Tags in den Element-Tag zu schreiben) und Entities
mit !ENTITY definiert.
Einbindung
DTDs werden in die XML-Datei eingebuden mit
<!DOCTYPE ROOTELEMENT SYSTEM "DTDDATEINAME.dtd">
PCDATA
Tags können als Inhalt entweder weitere Tags und/oder
Buchstaben haben (z.B. <p> hallo Welt </p>).
Diese Buchstaben werden in DTDs entweder als
CDATA (character data, für Attribute) oder als
PCDATA (parsed character data) definiert.
Elemente
Tags (entsprechen Elementen) werden mit dem Schlüsselwort
<!ELEMENT tagname> definiert.
---myfirst.dtd
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Schaden tut der XML-Header nicht-->
<!ELEMENT hello-world (#PCDATA)>
---myfirst.xml
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<?xml-stylesheet href="myfirst.xsl" type="text/xsl"?>
<!DOCTYPE hello-world SYSTEM "myfirst.dtd">
<hello-world>
Hallo Welt!
</hello-world>
Beachten Sie die neue Zeile !DOCTYPE und die absolute Pfadangabe des
DTDs: hier sind keine relativen Pfade möglich.
leere Tags und volle Tags
Das Schlüsselwort EMPTY definiert Tags, die keinen Inhalt haben dürfen
(wie etwa das br/-Tag in HTML)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!ELEMENT hello-world EMPTY>
dahingehen definiert ANY,
dass jedes Tag in diesem Tag vorkommen darf.
Tags erlauben
Innerhalb der Klammern nach dem Tagnamen können Sie allerdings auch
eine Liste mit Tags angeben, die vorkommen sollen oder müssen.
Das Beispiel verlangt im Tag hello-world nach genau einem Vorkommen des Tags
name, das Text enthalten kann.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!ELEMENT hello-world (name)>
<!ELEMENT name (#PCDATA)>
Weitere Tags werden mit Kommata getrennt
<?xml version="1.0" encoding="ISO-8859-1"?>
<!ELEMENT hello-world (name, alter)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT alter (#PCDATA)>
Um die Anzahl anzugeben, in der Tags vorkommen dürfen, benutzt
man die Zeichen
*
|
für keinmal, einmal oder öfter
|
+
|
für mindestens einmal oder öfter
|
?
|
für keinmal oder einmal
|
(element1 | element2)
|
für Element1 ODER Element2
|
Beispiel in DTD.DTD bzw. DTD.XML .
Sie sehen dort auch, dass Sie die Reihenfolge der Tags einhalten müssen.
PCDATA können Sie in die Tags auch einbringen;
um zu versuchen, dies
<p>Dies ist <u>ein</u>
<i>Text mit <u>Unterstrich</u></i></p>
in einem DTD "legal zu machen", folgt
1) Muss P mit PCDATA, i oder u zu füllen sein
2) Muss i mit PCDATA oder u zu füllen sein und
3) Muss u mit PCDATA oder i zu füllen sein
daraus folgt
<!ELEMENT p (#PCDATA | i | u)*>
<!ELEMENT i (#PCDATA | u)*>
<!ELEMENT u (#PCDATA | i)*>
Da PCDATA | Sektionen laut Internet Explorer ("Mixed content model must be defined as zero or more('*'). ")
gesternt werden müssen, erklärt sich der * in der ersten Zeile.
Dieser würde normalerweise das Verwenden von mehreren Top-Level-P-Tags
ermöglichen, da das dann jedoch kein XML mehr wäre (
höchstens ein Top-Level-Tag) ergeben sich Schwierigkeiten wenn man's versucht.
Beachten Sie auch dass Sie im Doctype der XML-Datei das neue Top-Level-Tag
angeben müssen:
<!DOCTYPE p SYSTEM "dtd2.dtd">
Der Einfachheit halber habe ich das Beispiel unter
Samples/dtd2.dtd bzw. Samples/dtd2.xml
abgelegt.
Attribute
Attribute werden mit !ATTLIST definiert - so
<!ATTLIST p
name CDATA #REQUIRED
beschreibung CDATA #IMPLIED
autor CDATA "ich"
groesse (klein|mittel|gross) #IMPLIED
intoc (ja|nein) "ja"
>
wobei
#REQUIRED
|
bedeutet, dass das Attribut vom XML-Schreiber angegeben werden muss
|
""
|
den Defaultwert des Attributs angint und
|
(a|b|c)
|
bedeutet, dass das Modul den Wert a oder b oder c haben muss.
|
Da Atributnamen in einem Tag nur einmal benutzt werden dürfen,
entfällt der ganze Kram mit "mindestens einmal" und ?*+.
Um den Spaß vorwegzunehmen habe ich auch ein
Projekt gespeichert, dass sowohl aus DTD als auch aus
XML- und XSLT-Datei
besteht. Die Ausgabe zeigt sehr schön, dass
die Default-Attributwerte auch tatsächlich so interpretiert werden
(autor und intoc wurden ja nicht in der XML-Datei definiert).
Entities
Zwei Beispiele:
<!ENTITY myente "quaak">
<!ENTITY auml "ä">
Während der Aufruf von &myente; in der XML-Datei
quaak erzeugt ä ein ä.
Eine Weitergabe der Entity als
<!ENTITY auml "ä">
kommt übrigens aus zwei Gründen nicht in Frage:
Erstens kennt XML (nur XHTML!) gar kein ä sondern nur Unicode-Entities und
zweitens wäre das "infinite entity reference loop"
(drittens arbeiten wir sowieso im 8859-1-Zeichensatz und gebrauchen keine Entities für Umlaute ;))
Was weggelassen wurde
Nicht erwähnt habe ich Parameter Entity References
(Entities die in der DTD genutzt werden können und damit eine gewisse
Modularisierung erlauben - oft benutzte Zeichenketten kann man als
Parameter Entity zentralisieren), bedingte Abschnitte in der DTD und
Notationen.
Mit Parameter Entity References kann man auch andere DTDs in den
eigenen DTD importiert.