Websiteentwicklung: XML: Dokumenttypdefinition (DTD)

Dokumenttypdeklaration und Dokumenttypdefinition Bearbeiten

Wie bereits erwähnt, kann im Prolog eines XML-Dokumentes (und auch anderer SGML-Dokumente) eine Dokumenttypdeklaration angegeben werden. Diese dient dazu, auf ein Schema zu verweisen, nach welchem das XML-Dokument, allgemeiner Dokumente im jeweiligen Format strukturiert sind. Anhand des Schemas kann dann ein Dokument validiert werden, es kann also mit dem Darstellungsprogramm oder einem zusätzlichem Programm geprüft werden, ob das Dokument die mit dem Schema vorgegebene Struktur einhält. Mit einer Dokumenttypdeklaration wird auf eine Dokumenttypdefinition verwiesen. Diese ist in einer eigenen SGML-Sprache verfaßt, die kein XML-Format ist. Es gibt auch andere Schema-Sprachen, die für XML-Formate verwendet werden können, die aber andere Mechanismen aufweisen können, um auf eine Datei zu verweisen, mit welcher die Einhaltung des Schemas geprüft werden kann. Diese anderen Schema-Sprachen, insbesondere die XML-Formate darunter, wurden erst nach der Spezifikation von XML entwickelt, auch daher finden in der XML-Spezifikation nur Dokumenttypdefinition und Dokumenttypdefinition eine Erwähnung, was die Nutzung anderer Schema-Sprachen allerdings nicht ausschließt.

Dokumenttypdeklarationen können in verschiedener Form auftreten. Die minimale Form im Prolog eines XML-Dokumentes sieht wie folgt aus:

<!DOCTYPE html>

Der Anfang '<!DOCTYPE ' und das Ende '>' sind in jeder Dokumenttypdefinitionen so zu notieren. Dazwischen kann man nach Bedarf Leerzeichen verteilen. Diese minimale Form gibt nur noch zusätzlich den Namen des Wurzelelementes an, gibt sonst keine weitere Information über die mögliche Struktur von Dokumenten. Hier weiß man also nur, daß das Wurzelelement den Namen html hat.

So für sich allein ergibt diese minimale Form keinen großen Sinn, hilfreich ist diese Konstruktion allerdings, wenn man direkt in die Dokumenttypdeklaration Strukturen einer Dokumenttypdefinition einfügt, dies ist die sogenannte interne Teilmenge der DTD. Etwa hat das Format SVG tiny 1.2 keine offizielle Dokumenttypdefinition mehr, die Struktur wird als Prosa definiert. Bei dem Graphikformat SVG ist es allerdings recht bequem und nützlich, für sich wiederholende Strukturen Entitäten definieren zu können, dies kann in der Dokumenttypdeklaration gemacht werden, etwa so:

<!DOCTYPE svg
   [<!ENTITY Pfad "M200,300 L300,100">
   ]
>

Beim Graphikformat Skalierbare Vektorgraphik ist das Wurzelelement immer svg, daher steht dies als Minimalinformation in der Dokumenttypdeklaration. Nach Leerzeichen folgt dann in eckigen Klammern '[' und ']' die Dokumenttypdefinition, die hier lediglich aus einer Definition einer Entität 'Pfad' besteht. Im Dokument verwendet man das dann durch die Notation '&Pfad:'. In diesem Fall ist das einfacher Text; sofern man SVG kennt, ist klar, man kann das als Teil des Wertes des Attributes d des Elementes path verwenden, es handelt sich um Kommandos, die Pfade repräsentieren. Die Entität läßt sich nun an geeigneter Stelle in den Attributwert einfügen und somit im Dokument immer wieder verwenden. Typisch ist der Text mit solchen Pfadangaben länger, von daher kann es sich also lohnen, für lange Sequenzen, die öfter im Dokument auftreten, solche Entitäten zu definieren. Neben (Teilen von) Attributwerten und Texten kann man auch ganze Elemente und Elementgruppen definieren und damit durch Angabe der Entität wiederverwenden.

Die genaue Syntax, wie man Entitäten und andere Strukturen definiert, wird in den folgenden Abschnitten erläutert.

Neben der internen Teilmenge der DTD kann es auch eine externe Teilmenge der DTD geben. Dabei unterscheidet man zwei Möglichkeiten, mit der ersten Notation wird angegeben, dass die DTD zunächst einmal nur für das referenzierende Dokument relevant ist, man definiert damit also eigentlich kein allgemein verwendbares Format. Mit der zweiten Möglichkeit bietet man die Dokumenttypdeklaration zur allgemeinen Verwendung an. Für letzteres gibt es eine weitere Notationsmöglichkeit.

Für die einfache Variante sieht die Dokumenttypdeklaration wie folgt aus:

<!DOCTYPE name SYSTEM "URI">

name ist dabei wieder der Name des Wurzelelementes, 'SYSTEM' ist ein Schlüsselwort, welches darauf hinweist, dass darauf nach Leerzeichen eine Angabe folgt, unter welcher URI die externe Datei mit der DTD zu finden ist, diese folgt dann in einfachen oder doppelten Anführungszeichen. Danach kann bei Bedarf auch noch eine interne Teilmenge eingefügt werden, also sinngemäß so:

<!DOCTYPE meins SYSTEM "meins.dtd"
   [<!ENTITY Ding "Das ist mein Ding!">
   ]
>

meins ist alo der Name des Wurzelelementes, die externe Teilmenge der DTD findet sich im Dokument 'meins.dtd', hier eine relative Pfadangabe, eine absolute geht natürlich auch. Danach wird als interne Teilmenge noch eine Entität definiert, die offenbar nur für dieses Dokument relevant ist, während man die externe Teilmenge ja auch von anderen Dokumenten aus referenzieren kann.

Soll die externe Teilmenge noch breitere Verwendung finden, macht man sie öffentlich, statt dem Schlüsselwort 'SYSTEM' notiert man dann 'PUBLIC', danach separiert mit mindestens einem Leerzeichen folgt dann die Angabe einer Kennung, dies ist einfacher Text, welcher Angaben zum Herausgeber und Format enthalten soll. Danach folgt dann wieder separiert mit mindestens einem Leerzeichen die Angabe einer URI der DTD, sinnvoller Weise in dem Falle meistens wohl eine absolute Adresse, wenn das Format allgemein verwendbar sein soll. Dach kann wieder die interne Teilmenge der DTD folgen.

Typisches Beispiel (SVG 1.1):

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

oder mit interner Teilmenge der DTD:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"
   [<!ENTITY Pfad "M200,300 L300,100">
   ]
>

oder auch XHTML+RDFa 1.1 XHTML+RDFa 1.1:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.1//EN"
    "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-2.dtd">

oder XHTML1.1 (Modularisierte Variante):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

Gemäß der Kurznotation der Dokumenttypdeklaration gilt folgendes:

doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubset ']' S?)? '>'
intSubset ::= (markupdecl | DeclSep)*
DeclSep ::= PEReference | S
markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment
ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral
SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]

PEReference, elementdecl, AttlistDecl, EntityDecl, NotationDecl werden in späteren Abschnitten im Zusammenhang mit der Dokumenttypdefinition erläutert.

Erstellen von Regeln in der Dokumenttypdefinition Bearbeiten

Damit ein XML-Dokument wohlgeformt ist, muss es sich an die Wohlgeformtheitsregel halten (richtige Verschachtelung, geschlossene Elemente, und so weiter). Die Dokumenttypdefinition, kurz DTD genannt, regelt, welche Elemente und Attribute in einem XML-Dokument gültig sind, wie oft sie verwendet werden können, oder welche Daten sie umfassen dürfen. Dies ist nötig, da, wie unter Aufbau eines XML-Dokumentes beschrieben, die Namensvergabe für Elemente freigestellt ist. Hält sich ein wohlgeformtes XML-Dokument an die in einer DTD formulierten Regeln, ist es auch gültig.

XML empfiehlt ansonsten, daß auch die vordefinierten XML-Attribute in der DTD definiert sein sollten, wenn sie im Dokument verwendet werden. Ein Validator muß dann nicht notwendig wissen, dass diese Attribute allgemein in XML vordefiniert sind, es kann sich also auch um einen allgemeinen Validator handeln, der beliebige SGML-Dokumente anhand von DTDs prüfen kann, nicht nur XML-Dokumente. Bei der Verwendung von Präfixen für Namensräume kann es hinsichtlich einer Validierung anhand einer DTD auch helfen, Elemente mit den verwendeten Präfixen in der DTD zu notieren, dann braucht der Validator keine Kenntnis von der Verarbeitung von Namensraumangaben haben und findet wirklich alle verwendeten Strukturen in einer referenzierten DTD.

Meistens legen Autoren von Dokumenten, die in einem XML-Format geschrieben sind, nicht selbst Dokumenttypdefinitionen an, sondern halten sich nur an das, was in einer Dokumenttypdefinition oder einem anderen Schema oder der Prosaspezifikation eines Formates steht. Von daher ist es für Autoren von Dokumenten nicht notwendig, Detailkenntnisse über Dokumenttypdefinitionen zu haben, nützlich sind Kenntnisse darüber indessen schon, auch um in solchen Dokumenttypdefinitionen schnell nachsehen zu können, welche Elemente und Attribute es gibt und wie diese zu verschachteln sind. Man muß allerdings auch sagen, dass Dokumenttypdefinitionen für oft genutzte umfangreiche Formate wie XHTML, SVG oder MathML von Experten geschrieben wurden, die die Möglichkeiten der Notation voll ausgeschöpft haben, auch um flexibel schnell Änderungen an der Definition vornehmen zu können, etwa neue Attribute für alle Elemente mit einer kleinen Änderung einfügen zu können, von daher haben Dokumenttypdefinitionen durch die ausgiebige Verwendung von Abkürzung und deren Wiederverwendung einen hohen Abstraktionsgrad und man muß sich erst einarbeiten, um diese Dokumente zu durchschauen.

Für Personen, die für eigene oder allgemeiner neue Formate Dokumenttypdefinitionen erstellen, ist es natürlich sehr wichtig, die Notation genau zu kennen und effektiv zu nutzen. Für diese Personengruppe kann es natürlich sehr nützlich sein, sich die Dokumenttypdefinitionen für etwa XHTML, SVG oder MathML genauer anzusehen, um zu lernen, wie man solche Dokumente geschickt schreibt, Formate geschickt modularisiert und einfach aktualisierbar hält.

Bestandteile einer Dokumenttypdefinition werden wieder in Kurznotation präzise definiert. Diese Bestandteile nutzen aber selbst wieder die Kurznotation, um zu definieren, welche Elemente in welchen und in welcher Reihenfolge verwendet werden dürfen, welche Attribute es gibt, welchen Wert diese haben dürfen, wie Entitäten definiert werden und wie Abkürzungen, ebenfalls Entitäten definiert werden, die in der Dokumenttypdefinition selbst verwendbar sind.

Kurznotationen (in den folgnden Abschnitten gibt es dazu Beispiele und Erklärungen in Prosa):

elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')'
children ::= (choice | seq) ('?' | '*' | '+')?
cp ::= (Name | choice | seq) ('?' | '*' | '+')?
choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')'
seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'

AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
AttDef ::= S Name S AttType S DefaultDecl
DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
AttType ::= StringType | TokenizedType | EnumeratedType
StringType ::= 'CDATA'
TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
EnumeratedType ::= NotationType | Enumeration
NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'

NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
Name ::= NameStartChar (NameChar)*
Names ::= Name (#x20 Name)*
Nmtoken ::= (NameChar)+
Nmtokens ::= Nmtoken (#x20 Nmtoken)*

EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' | "'" ([^%&'] | PEReference | Reference)* "'"
AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"

EntityDecl ::= GEDecl | PEDecl
GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
EntityDef ::= EntityValue | (ExternalID NDataDecl?)
PEDef ::= EntityValue | ExternalID
NDataDecl ::= S 'NDATA' S Name

Reference ::= EntityRef | CharRef
EntityRef ::= '&' Name ';'
PEReference ::= '%' Name ';'

conditionalSect ::= includeSect | ignoreSect
includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)

NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
PublicID ::= 'PUBLIC' S PubidLiteral

Zu TokenizedType: Das sind spezielle Typen, teils bereits durch die gennannte Syntax festgelegt, teils auch mit speziellen Ergänzungen:
ID - entspricht der Namensproduktion (Name), der Wert darf aber nur einmal in Dokument vorkommen.
IDREF - der Wert eines ID im selben Dokument, um das Element mit dieser ID zu referenzieren.
IDREFs - Liste mit mehreren IDREF, Listenseparatur gemäß der von Namenslisten (Names).
ENTITY - entspricht der Namensproduktion (Name), der Wert ist eine Entität in der DTD.
ENTITIES - Liste mit mehreren ENTITY, Listenseparator gemäß der von Namenslisten (Names).
NMTOKEN - entspricht der Produktion von Nmtoken.
NMTOKENS - entspricht der Produktion von Nmtokens.

Ein Beispiel für eine DTD:

<!ELEMENT Person (Name,Kind*)>
<!ELEMENT Kind (Name)>
<!ELEMENT Name (#PCDATA)>

Diese DTD sagt aus, dass es ein Element Person gibt, mit den Unterelementen Name und Kind, wobei Kind öfter als einmal vorkommen darf. Des Weiteren bestimmt diese DTD, dass Name nur mit Zeichendaten gefüllt sein darf.

Ein wohlgeformtes gültiges XML-Dokument für Umlaute nach ISO-8859-1 sähe dann so aus:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE  Person SYSTEM "Person.dtd">

<Person>
    <Name>Manfred Müller</Name>
    <Kind>
        <Name>Olivia Müller</Name>
    </Kind>
    <Kind>
        <Name>Marc Müller</Name>
    </Kind>
</Person>

Erstellen eines DTD-Schemas Bearbeiten

Zur Erstellung einer DTD wird lediglich ein Texteditor benötigt. Um die DTD in einer externen Datei unterzubringen, speichern Sie im Anschluss die Definitionen in einer Datei mit der Dateiendung .dtd. Der Namen kann ansonsten frei gewählt werden. Die Endung ist im Grunde auch nur Konvention, dient aber einigen Datei- oder Betriebssystemen dazu, die Datei als DTD zu identifizieren. Diese Datei enthält dann direkt die Definitionen für Elemente, Attributlisten, Entitäten etc gemäß der Syntax, wie sie bereits als Kurznotation angegeben wurde.

Einbinden einer DTD in ein XML-Dokument Bearbeiten

Wie bereits erläutert, gibt es zwei Wege eine DTD in ein XML-Dokument einzubinden. Entweder über Interne DTDs oder über Externe DTDs. Oben in diesem Kapitel gibt es bereits einige Beispiele zur Dokumenttypdeklaration.

Interne DTD Bearbeiten

Wie bereits zu der Dokumentypdeklaration ausgeführt, kann die Dokumenttypdefinition auch direkt in dieser notiert werden, somit also direkt in ein XML-Dokument integriert werden. Sämtliche Deklarationen werden dann von <!DOCTYPE Wurzelelement [ sowie ]> umklammert. Dies Vorgehen ist primär sinnvoll, wenn die DTD nur für dieses Dokument gedacht ist. Da dies allerdings auch nur eine interne Teilmenge zu sein braucht, kann die Methode auch sinnvoll sein, um darin (nur) jene Strukturen zu definieren, die für dieses spezielle Dokument gebraucht werden und sonst nicht definiert sind, etwa weil sie nur in diesem Dokument eine Anwendung finden.

Beispiele finden sich bereits weiter oben im Abschnitt über Dokumenttypdeklarationen, ein weiteres Beispiel: für ein komplettes XML-Dokument mit kompletter interner DTD:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE  Person [
    <!ELEMENT Person (Name,Kind*)>
    <!ELEMENT Kind (Name)>
    <!ELEMENT Name (#PCDATA)>
]>

<Person>
    <Name>Manfred Müller</Name>
    <Kind>
        <Name>Olivia Müller</Name>
    </Kind>
    <Kind>
        <Name>Marc Müller</Name>
    </Kind>
</Person>

Externe DTD Bearbeiten

Eine DTD oder der externe, allgemeiner brauchbare Teil der DTD kann auch in einer externen Datei untergebracht werden. Diese Datei mit dem externen Teil wird dann in der Dokumenttypdeklaration referenziert, Beispiele gibt es bereits weiter oben, ein weiteres Beispiel:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE  Person SYSTEM "Person.dtd">

<Person>
    <Name>Manfred Müller</Name>
    <Kind>
        <Name>Olivia Müller</Name>
    </Kind>
    <Kind>
        <Name>Marc Müller</Name>
    </Kind>
</Person>

Deklarationen Bearbeiten

In der DTD werden die Strukturen des XML-Formates definiert. Eine Struktur wird in der DTD deklariert, also es wird angegebenen, was wie im XML-Dokument verwendet werden darf. Die Reihenfolge ist dabei nicht relevant. Später auftretende Teile können im Konfliktfalle aber früher auftretende aktualisieren oder ergänzen, Abkürzungen müssen indessen nicht unbedingt erst definiert sein, bevor sie verwendet werden. Die interne Teilmenge der DTD gilt in diesem Sinne als später als die gegebenenfalls vorhandene externe Teilmenge.

Generell kann man in der DTD-Datei auch Kommentare in der bereits definierten Syntax verwenden, allerdings nur außerhalb der im Folgenden erläuterten Deklarationen

Element-Deklaration Bearbeiten

Alle in einer DTD deklarierten Elemente können in einem XML-Dokument genutzt werden. Im Umkehrschluss bedeutet dies, dass nicht-deklarierte Elemente nicht verwendet werden dürfen. Mit der DTD wird zudem angegeben, in welchen Elementen die Elemente notiert werden dürfen, im Bedarfsfalle auch in welcher Reihenfolge oder welcher Anzahl.

In der DTD ist es nicht möglich anzugeben, welches Element das Wurzeldokument ist, dies wird also nur in der Dokumenttypdefintion innerhalb der XML-Datei angegeben. So oder so ist das Wurzelelement wie jedes andere auch in der DTD zu deklarieren. Aus beidem zusammen ergibt sich dann erst, wie Dokumente zu strukturieren sind. Mit einer DTD-Datei allein als externer Teilmenge der Dokumenttypdefinition läßt sich also nicht bestimmen, wie man konkret ein Dokument in dem betreffenden Format erstellt, weil die Information zum Wurzelelement fehlt. Rein Informativ kann man natürlich mittels eines Kommentars in die DTD-Datei reinschreiben, welches Element das Wurzelelement ist oder welche Elemente es sein können.

Ein bestimmtes Element darf nur exakt einmal deklariert werden, der Name des Elementes ist also eindeutig. Das schließt somit aus, dass Inhalt oder Attribute eines Elementes abhängig vom Elternelement sein können. Bei komplexeren Formaten möchte man dieses aber häufig haben, man denke etwa an die Elemente a, form und object in XHTML. Das Element a darf etwa keine weiteren Elemente a als Nachfahren haben, was per DTD nicht formulierbar ist, weil a weitere inzeilige Elemente enthalten darf, welche wiederum a-Elemente enthalten dürfen, falls sie nicht selbst Nachfahren von einem a sind. Ähnliches gilt in XHTML für das Element form, welches auch keine weiteren Elemente form enthalten darf. object kann in XHTML-Dokumenten wiederum sowohl innerhalb von head notiert werden als auch innerhalb von body. Entsprechend sollte aber eigentlich der mögliche Inhalt von object ganz anders sein, je nachdem, ob das Element in head oder body notiert ist. Mit einer DTD läßt sich dies nicht angeben.

Die genaue Syntax einer Element-Deklaration ist bereits in Kurznotation angegeben. In Prosa-Form: Sie beginnt mit der Zeichenkette '<!ELEMENT' und endet mit '>'. Nach Leerzeichen folgt auf '<!ELEMENT' der Name des Elementes, wobei der Name der Namensproduktion entspricht. Darauf erfolgt eine Angabe über den Inhalt.

Beispiel für die Deklaration eines inhaltsleeren Elementes img:

<!ELEMENT img EMPTY>

Beispiel für die Deklaration eines Elementes metadata, welches jeglichen (deklarierten) Inhalt enthalten darf:

<!ELEMENT metadata ANY>

Das löst also etwa nicht das Problem, dass das Element eventuell Elemente aus beliebigen Namensräumen enthalten darf, wie es etwa das Format SVG für das gleichnamige Element vorsieht. Gemäß obiger Angabe aber wären neben interpretiertem Text darin verwendbare Elemente also erst einmal nur jene, die in der DTD auch deklariert sind, einschließlich sogar metadata selbst.
Gerade das will man in SVG allerdings nicht, man will alle Elemente außer denen von SVG dort erlauben, also gerade jene, die nicht in der DTD stehen, was allerdings die Möglichkeiten einer DTD übersteigt und somit nur in der Prosa der Spezifikation zu finden ist.
Gemäß der DTD für SVG 1.1 etwa wäre als Inhalt nur #PCDATA erlaubt (interpretierter Text, siehe nächstes Beispiel), was aber gemäß Spezifikation eine zu starke Einschränkung ist. Bei dem eigentlich relevantem Inhalt wird ein Validator, welcher nur der DTD folgt, also eine falsche Fehlermeldung ausgeben, wenn wie per Prosa beabsichtigt, in dem Element Elemente aus anderen Namensräumen notiert sind.

Sofern das Element nicht leer ist oder alles enthalten darf, steht die Angabe über den möglichen Inhalt immer in Klammern.

Beispiel für die Deklaration eines Elementes Telephonnummer, welches nur interpretierten Text als Inhalt enthalten darf:

<!ELEMENT Telephonnummer (#PCDATA)>

Bei einer Telephonnummer könnte man nun meinen, die besteht nur aus einer Ziffernfolge, neuerdings eventuell auch noch aus Buchstaben, jedenfalls wohl keine Satzzeichen und dergleichen. Allerdings kann man den Text-Inhalt eines Elementes mit einer DTD nicht weiter einschränken, dazu wäre dann eine andere Schema-Sprache zu verwenden.

Hat ein Element mehrere mögliche Unterelemente in einer bestimmten Reihenfolge, so notiert man die Namen der gewünschten Reihenfolge nach, separiert je mit einem Komma ',' und optionalen Leerzeichen:

<!-- Wurzelelement eines XHTML-Dokumentes -->
<!ELEMENT html (head, body)>

Manchmal will man auch angeben, dass entweder das eine oder das andere oder ein weiteres etc Element verwendet werden darf, dabei separiert man die sich gegenseitig ausschließenden Möglichkeiten mit einem '|', wie bereits von der Kurznotation her bekannt:

<!ELEMENT Geschlecht 
  (männlich | weiblich | sächlich 
  | gemischt | neutral | unbestimmt 
  | nichtObjektivierbar | keineAngabe)>

Bekanntlich ist die Geschichte mit dem Geschlecht eine heikle Sache - grammatikalisch, biologisch, psychologisch? Vielleicht ist es weiser, #PCDATA als erlaubten Inhalt anzugeben? Vorteil der expliziten Auswahl zwischen einer endlichen Menge von Möglichkeiten ist immerhin, dass man das noch mit Programmen automatisch auswerten kann, was bei #PCDATA schon schwierig wird. Psychologie dürfte ohnehin schwierig mit einfachen Programmen zu erfassen sein ...
Man kann natürlich auch Kompromisse machen, die statistisch häufigen Angaben maschinenlesbar machen, den Rest mit freiem Text:

<!ELEMENT Geschlecht 
  (männlich | weiblich | sächlich 
  | keineAngabe | #PCDATA)>

Oder man macht es so:

<!ELEMENT Geschlecht 
  (männlich | weiblich | sächlich 
  | keineAngabe | NN)>
<!ELEMENT männlich  EMPTY>
<!ELEMENT weiblich  EMPTY>
<!ELEMENT sächlich  EMPTY>
<!ELEMENT keineAngabe  EMPTY>
<!ELEMENT NN  (#PCDATA)>

Dann kann man mittels NN (noch zu nennen) eine individuelle Angabe in Textform machen, während die anderen Elemente leer bleiben.

Oft können Elemente auch mehrmals oder optional notiert werden, wie von der Kurznotation bereits bekannt, steht dabei ein angehängtes Zeichen für die erlaubte Anzahl, '?' für 0 oder 1 mal, + für mindestens einmal oder öfter, * für beliebig oft, auch gar nicht:

<!ELEMENT Name (Anrede, Titel?, Vorname+, Nachname*)>

Hier hat man also im Element Name zunächst exakt einmal Anrede zu notieren, darauf optional maximal einmal Titel, dann mindestens einen oder mehrere Elemente Vorname und dann beliebig viele Elemente vom Typ Nachname. Dazu paßt dann zum Beispiel folgendes XML-Fragment, wenn wir davon ausgehen, dass für alle Unterelemente #PCDATA als Inhalt erlaubt ist:

<Name>
<Anrede>Freifrau</Anrede>
<Titel>Prof. Dr. rer.nat. Dr. h.c. Prinzessin</Titel>
<Vorname>Anna</Vorname>
<Vorname>Marie</Vorname>
<Vorname>Luise</Vorname>
<Vorname>Liselotte</Vorname>
<Nachname>Musterfrau</Nachname>
<Nachname>von Humpenstedt</Nachname>
<Nachname>zu Lotterburg</Nachname>
</Name>

Aufgrund der Einschränkungen auf nur ein erlaubtes Element Titel muß man also nun alle Titel der Dame in diesem einen Element unterbringen, während man die Sammlung von Vor- und Nachnamen auf mehrere Elemente verteilen darf. Als Entwickler des Formates könnte man sich nun überlegen, ob es wirklich weise und ratsam ist, nur ein Element Titel zu erlauben oder ob man da noch weiter mit Unterelementen differenzieren sollte, statt nur Text zu erlauben. Bei dem ganzen Abkürzungskram im Titel, braucht man da nicht noch weitere Elemente, damit man all die Abkürzungen erläutern kann? Auch bei den Namen könnte man nun verfeinern und sich überlegen, wie man den Rufnamen angibt, etwa mit einem Attribut? Sollte man vielleicht auch noch ein Element für Spitznamen oder Kosenamen ergänzen?

Man erkennt schon an dem Beispiel, eine saubere, allgemeingültige DTD für eine breitere Anwendung zu schreiben, ist eine knifflige Angelegenheit, die nicht nur rein technisches Wissen und Können erfordert, sondern auch eine Menge Kenntnisse zu der Thematik, welche mit dem XML-Format behandelt wird.
Selbst als Nutzer eines solches Formates kann man schnell ins Schleudern geraten, wenn man die Spezifikation nicht kennt. Sind 'Freifrau' und 'Prinzessin' eher ein Teil der Anrede oder doch des Titels? Kann jemand überhaupt gleichzeitig Freifrau und Prinzessin sein (wäre die Anrede dann nicht ohnehin impliziert 'Hochwohlgeborene')? Gehören die Nachnamen nicht vielleicht doch alle in ein Element, weil die Frau nun einmal insgesamt so heißt und man den Nachnamen nicht weiter fragmentieren darf? Oder gehören 'von Humpenstedt' und 'zu Lotterburg' gar noch zum Titel (Adelstitel oder Namensbestandteil)? Oder hängt alles von der Zeit und dem Ort ab, wann und wo die Frau lebt?

Was tun, wenn es auf die Reihenfolge nicht ankommt? Dazu kann man anders oder zusätzlich klammern:

<!ELEMENT head (title, (style|meta|script|object)*)>

Das hat Ähnlichkeit mit der Deklaration des Elementes head von XHTML. Dort muß der title aber nicht unbedingt an erster Stelle stehen. Also paßt dafür eher dieses:

<!ELEMENT head ((style|meta|script|object)*, title, (style|meta|script|object)*)>

So können dann auch etwas kompliziertere Anforderungen an Anzahl und Reihenfolge notiert werden, wobei man in einer tatsächlichen DTD für XHTML die Angaben auf einem etwas höheren Abstraktionsniveau mit Abkürzungen realisiert sieht, man ahnt schon hier an der doppelten Notation der optionalen Elemente vor und nach dem exakt einmal irgendwo zu notierenden title, dass man bei einer größeren Elementkollektion mit Gruppierung zu verschiedenen Abkürzungen einfacher und knapper notieren kann, trotzdem aber noch viel Spaß hat, wenn Elemente in beliebiger Reihenfolge, aber nur in einer bestimmten, je nach Element aber anderen Anzahl auftreten dürfen.

Attributlisten-Deklaration Bearbeiten

Elemente können auch Attribute haben. Wenn sie welche haben, sind sie in der DTD mit einer Attributlisten-Deklaration anzugeben. Da ein Element mehrere Attribute haben kann, ist die Syntax für solche eine Deklaration etwas komplizierter als für ein Element.

Die einfachste Variante:

<!ELEMENT br >
<!ATTLIST br >

Offenbar hat dann das Element br keine Attribute, das muß man dann allerdings auch nicht extra notieren.

Gibt es ein Attribut, so sieht die Deklaration etwa so aus:

<!ELEMENT liste >
<!ATTLIST liste reihenfolge (vorwärts|rückwärts) #IMPLIED >

Nach dem Elementnamen folgt der Attributname, dann der Werteraum für den Attributwert, dann kann eine Angabe dazu folgen, ob das Attribut notiert werden muß (#REQUIRED) oder optional ist (#IMPLIED) oder einen festen Wert hat (#FIXED), anschließend kann ein Vorgabewert notiert werden, sinnvoll primär für #IMPLIED und #FIXED. Generell wird #IMPLIED aber eher notiert, wenn kein Wert vorgegeben wird, gibt man den Wert vor, ist implizit festgelegt, dass die Angabe nicht erforderlich ist, sofern nicht angegeben, aber der Vorgabewert verwendet wird. Bei Vorgabewerten ist zu bedenken, dass mit solchen die Interpretation des Dokumentes davon abhängt, ob ein interpretierendes Programm die DTD liest, beziehungsweise das Format hinsichtlich der Vorgabe bereits kennt oder dies nicht der Fall ist. Ohne Kenntnis können die Vorgabewerte bei der Interpretation auch nicht berücksichtigt werden.

Also Beispiel mit Vorgabe:

<!ELEMENT liste >
<!ATTLIST liste reihenfolge (vorwärts|rückwärts) "vorwärts" >

Hat man etwa die DTD zu einer bestimmten Version eines Formates, ist es meist sinnvoll, dass Autoren von Dokumenten die Version angeben, damit die Dokumente entsprechend der Version prüfbar sind und bei einer falschen Version die Prüfung fehlschlägt, etwa so:

<!ELEMENT wurzel >
<!ATTLIST wurzel version CDATA #FIXED "1.0" >

Ist nun etwas anderes als '1.0' für die Version im Dokument notiert, sollte eine Prüfung anhand der DTD eine Fehlermeldung ergeben.

CDATA sagt hier einfach, dass in dem Attribut interpretierter Text stehen darf, was dann erst danach mit #FIXED und der Wertangabe eingeschränkt wird.

Will man ansonsten, dass das Attribut immer explizit angegeben wird, aber der Wert nicht festgelegt ist, so schreibt man etwa:

<!ELEMENT image >
<!ATTLIST image source CDATA #REQUIRED >

Prinzipiell ist es möglich, einen Vorgabewert anzugeben, weil man das Attribut aber ohnehin immer explizit angeben muß, ist dies sinnlos.

  1. REQUIRED wird man also insbesondere dann fordern, wenn einerseits das Attribut wichtig für die Funktion oder die Bedeutung des Elementes ist, aber nicht per Vorgabewert etwas festgelegt werden kann, was meistens sinnvoll ist, man sich die Angabe also meist sparen kann, indem die Vorgabe impliziert wird.

In diesem Falle soll vermutlich eine externe Datei mit einem Bild zur Einbettung referenziert werden, da man bei der Anfertigung der DTD meist natürlich nicht weiß, welches Bild, kann man da keinen Vorgabewert angeben, da das Element aber ohne Angabe einer Quelle für das Bild sinnlos ist, ist die Angabe folglich erforderlich.

Wenn man mag, kann man so fortfahren und für jedes einzelne Attribut eine Deklaration angeben, man kann aber auch einfach weitere Attribute anhängen:

<!ELEMENT bild >
<!ATTLIST bild quelle CDATA #REQUIRED
               alternativtext CDATA #REQUIRED
               höhe CDATA "100%"
               breite CDATA "100%"
               typ ( svg | png | jpeg ) "svg"
               frag ID #IMPLIED
               ref IDREF #IMPLIED
               reftext CDATA #IMPLIED
>

So hat man also einen ganzen Satz von Attributen für das Element bild mit einer Deklaration eingeführt.

Sofern man die möglichen Werte nicht explizit als entweder-oder-Aufzählung angibt, verwendet man eines von neun Schlüsselwörtern, um anzugeben, welchen Wert ein Attribut habe kann. Die Aufzählungsliste steht in Klammern, diName> e Alternativen sind jeweils mit '|' getrennt, jede Alternative ist ein NMTOKEN, siehe auch folgende Liste und obige Kurznotation.

Mögliche Schlüsselwörter:

  • CDATA - interpretierter Text, das wird praktisch immer verwendet, wenn sonst nichts paßt.
  • NMTOKEN - das entspricht einer Zeichenfolge gemäß der Namensproduktion, allerdings ohne die Einschärnkungen für das erste Zeichen
  • NMTOKENS - das ist ein NMTOKEN oder mehrere davon, dann durch Leerzeichen separiert
  • ID - das entspricht einer Zeichenfolge gemäß der Namensproduktion, das Attribut dient als Fragmentidentifizierer, kein anderes Element im Dokument darf also das gleiche Attribut mit dem selben Wert haben.
  • IDREF - das entspricht einer Zeichenfolge gemäß der Namensproduktion, damit wird auf ein Element verwiesen, welches ein Attribut vom Typ ID notiert hat und zwar mit demselben Wert wie der für das IDREF, das stellt also einen Verweis auf den Fragmentidentifizierer dar.
  • IDREFS - das sind mehrere IDREF, jeweils mit Leerzeichen separiert, damit kann man also Listen von Fragmenten referenzieren.
  • ENTITY - der Wert ist eine Entität, die anderweitig in der DTD definiert wurde, wird in Zusammenhang mit der Deklaration von Entitäten genauer erläutert.
  • ENTITIES - das sind mehrere ENTITY, jeweils mit Leerzeichen separiert.
  • NOTATION - der Wert entspricht dem einer Notation, wird genauer erklärt in Zusammenhang mit der Deklaration von Notationen. Anders als bei den Listen kann man so per Notation auch Listenwerte angeben, die nicht der Namensproduktion entsprechen, etwa bei dem Beispiel mit den Typen für Bilder auch wirklich die Medientypen, also etwa 'image/svg' statt nur 'svg', denn '/' darf in der Namensproduktion nicht vorkommen.

Zu erkennen ist, bereits, sofern man nicht explizit eine Liste von Alternativen angibt, kann man den Wertebereich eines Attributes nicht besonders spezifisch mit der DTD prüfbar einschränken. Dazu wäre eine andere Schema-Sprache zu verwenden oder ein prüfendes Programm müßte einen Prüfmechanismus implementiert haben, welcher die weiteren, in der Prosa-Spezifikation angegebenen Einschränkungen bei einer Prüfung berücksichtigt.

Entitäten-Deklaration Bearbeiten

Es gibt zwei Typen von Entitäten-Deklarationen. Der eine dient dazu, jene Abkürzungen zu definieren, wie man sie im XML-Dokument selbst verwenden kann. Der andere wird auch Parameter-Entität genannt und dient dazu, Abkürzungen zu definieren, die in der DTD verwendet werden können.

Abkürzungen für das XML-Dokument Bearbeiten

Die Deklaration für den ersten Typ beginnt mit '<!ENTITY ' und endet wie die anderen auch mit '>'. Nach der Eingangszeichenkette und einem Leerzeichen folgt dann der Name der Abkürzung, wobei Name der Namensproduktion von XML folgt. Nach einem weiteren Leerzeichen folgt dann in Anführungszeichen die Zeichenkette, die abgekürzt werden soll. Neben einfachen Zeichenfolgen kann dies auch ein komplettes Element von der Anfangs- bis zur Endmarkierung sein - oder mehrere davon.

Beispiel einfache Zeichenkette:

<!ENTITY w3c "World Wide Web Consortium">

Innerhalb des XML-Dokumentes kann die Abkürzung dann dort notiert werden, wo interpretierter Text erlaubt ist, bei dem Beispiel so:

&w3c;

Variante mit einer Abkürzung für ein paar Elemente:

<!ENTITY kreise "<circle r='128' fill='#00f' />
<circle r='64' fill='#f0f' />
<circle r='32' fill='#f00' />
<circle r='16' fill='#ff0' />
<circle r='8' fill='#0f0' />
<circle r='4' fill='#0ff' />
<circle r='2' fill='#00f' />
">

Es ist dann natürlich darauf zu achten, dass in der Zeichenfolge, die abgekürzt wird, nicht die Anführungszeichen auftreten, welche verwendet werden, um die Zeichenfolge selbst zu umschließen. Die Abkürzung kann dann dort notiert werden, wo der abgekürzte Inhalt auch erlaubt ist. Das Abgekürzte muß insbesondere immer entweder einfacher interpretierter Text sein oder aber aus kompletten Elementen bestehen, man kann also nicht die Anfangsmarkierung in einer Abkürzung unterbringen und die Endmarkierung in einer anderen, mann kann so auch nur die Werte von Attributen abkürzen, nicht die komplette Angabe des Attributes oder nur seinen Namen. Das Abgekürzte kann wiederum selbst Entitäten enthalten, die dann entsprechend zu definieren sind. Zirkulare Abhängigkeiten oder Selbstreferenzierungen sind natürlich nicht erlaubt.

Statt nun das Abgekürzte in der DTD in Anführungszeichen anzugeben, kann man auch auf eine externe Datei mit dem abgekürzten Verweisen, statt dem Abgekürzten in Anführungszeichen wird dann zunächst das Schlüsselwort 'SYSTEM' notiert, worauf in Anführungszeichen die URI einer Datei steht, der das Abgekürzte zu entnehmen ist. Beispiel entsprechend dem vorherigen:

<!ENTITY kreise SYSTEM "kringel.ext" />

In der Datei 'kringel.ext' ist dann zu notieren:

<circle r='128' fill='#00f' />
<circle r='64' fill='#f0f' />
<circle r='32' fill='#f00' />
<circle r='16' fill='#ff0' />
<circle r='8' fill='#0f0' />
<circle r='4' fill='#0ff' />
<circle r='2' fill='#00f' />

Es muß sich dabei also nicht selbst um ein XML-Dokument handeln. Es handelt sich also ebenfalls um interpretierten Text oder um komplette Elemente wie in diesem Beispiel.

Im Bedarfsfalle kann es wichtig sein, die Kodierung dieser referenzierten Datei in der Datei anzugeben. Dazu kann man dem Inhalt eine XML-Deklaration voranstellen, die insbesondere eine Angabe zur Kodierung enthält, eine Angabe zur XML-Version ist nicht notwendig, etwa für vorheriges Beispiel:

<?xml encoding="ISO-8859-1"?>
<circle r='128' fill='#00f' />
<circle r='64' fill='#f0f' />
<circle r='32' fill='#f00' />
<circle r='16' fill='#ff0' />
<circle r='8' fill='#0f0' />
<circle r='4' fill='#0ff' />
<circle r='2' fill='#00f' />

Sofern das Abgekürzte nicht zu interpretieren ist, also eventuell darin befindliche kritische XML-Zeichen nicht maskiert sind, was etwa auch bei typischen Bildformaten/Binärdateien der Fall ist, so ist an die Deklaration noch eine Angabe zum Dateityp anzuhängen. Der Dateityp wird mit einer Notations-Deklaration definiert, siehe Abschnitt zu Notations-Deklarationen. Ein Beispiel sieht dann wie folgt aus:

<!ENTITY kreise SYSTEM "Bild.png" NDATA png />
<!NOTATION png SYSTEM "image/png">

Dass hier ein Medientyp angegeben wird, ist lediglich naheliegend, es ist allerdings nicht definiert, was man als Notation für diesen Zweck notiert. Mit einer Angabe der Notation und 'NDATA' wird lediglich angegeben, dass in Bild.png nicht zu interpretierender Inhalt vorhanden ist, welcher dann entsprechend auch nur dort durch die Abkürzung eingesetzt werden darf, wo solcher Inhalt erlaubt ist. Etwa könnte man so bei XHTML oder SVG mit base64 kodierte Bilder direkt per Abkürzung mit dem Pseudoprotokoll 'data' in ein Dokument einbetten, statt es ohne base64 zu referenzieren. In dem Format FictionBook2 (für digitale Bücher) etwa bettet man generell enthaltene Bilddateien direkt in das XML-Dokument ein, dieses Format hat also entsprechende Bereiche, wo man geeignete kodierte Bilddaten direkt in eine XML-Datei einbetten kann, diese kann man dann folglich auch mit einer Entität abkürzen und wiederverwenden, wobei FictionBook2 dafür eigene Mechanismen hat, die Bilddaten werden dort am Ende in Elementen mit Fragmentidentifizierer gelistet und im laufenden Inhalt werden dann nur diese Elemente referenziert, eine Wiederverwendung ist in dem Format also auch ohne eine DTD mit Entitäten problemlos möglich.

Per DTD fügt man ansonsten eine Bild-Abkürzung wie im folgenden Beispiel ein:

<!ELEMENT bild EMPTY>
<!ATTLIST bild quelle ENTITY #REQUIRED>
<!ENTITY kreise SYSTEM "Bild.png" NDATA png />
<!NOTATION png SYSTEM "image/png">

Und in der XML-Datei:

<bild quelle="kreise"/>

Abkürzungen für die DTD - Parameter-Entität Bearbeiten

Oft findet man in XML-Formate den Fall vor, dass viele verschiedenen Elemente dieselben Attribute habe, etwa die von XML vordefinierten Attribute. Da alle Attribute eines Elementes bei jedem Element einzeln anzugeben ist, würde das recht viel mehrfache Schreibarbeit bedeuten und das Ergänzen oder Streichen von solch allgemeinen Attributen in der DTD sehr erschweren. Allerdings gibt es für derartige Zwecke die Parameter-Entität, mit der sie wiederholende Teile einer DTD wie Attributlisten oder auch Listen von Kindelementen abkürzen lassen. Auch andere Teile der DTD wie Elementnamen oder Attributnamen oder ganze Deklarationen lassen sich damit abkürzen. Das ist für eine Modularisierung von DTDs relevant. Auch lassen sich so recht einfach DTDs für die Kombination von verschiedenen XML-Formaten erstellen, wobei man dann zum Beispiel alle Elemente eines Formates mit einem Präfix versieht. Damit solch Dokumente mit gemischten XML-Formaten per DTD validierbar ist, muß dafür der Name von Elementen dort also ebenfalls mit dem Präfix versehen werden, wenn der Validator rein nach der DTD vorgeht, also das Konzept von Namensräumen nicht versteht. Dafür muß dann in einer gemeinsamen DTD einfach nur die jeweilige Abkürzung für den Namen eines Elementes mit einer neuen Abkürzung überschrieben werden, welche das Präfix ersetzt.

Zur Referenzierung solcher Entitäten wird dem Namen der Parameter-Enität ein '%' statt des '&' vorangestellt, entsprechend wird dies Zeichen auch bei der Entitäten-Deklaration dem Namen mit einem Leerzeichen dazwischen vorangestellt.

Beispiel:

<!-- möglicher Inhalt von inzeiligen Elementen-->
<!ENTITY % inline.content "(#PCDATA | span | em | strong | q | cite)*">
<!-- Sprachattribute -->
<!ENTITY % i18n.attr "xml:lang CDATA #IMPLIED
dir (ltr | rtl) #IMPLIED" >
<!-- Kern-Attribute -->
<!ENTITY % core.attr "xml:id ID #IMPLIED
xml:lang CDATA #IMPLIED
xml:space (default|preserve) 'preserve'
xml:base CDATA #IMPLIED
class CDATA #IMPLIED
title CDATA #IMPLIED">
<!-- Attribute von inzeiligen Elementen -->
<!ENTITY % inline.attr "%core.attr; %i18n.attr;">

<!-- Element- und Attributdeklarationen, inzeilige Elemente -->
<!ELEMENT span %inline.content; >
<!ATTLIST span %inline.attr; >
<!ELEMENT em %inline.content; >
<!ATTLIST em %inline.attr; >
<!ELEMENT strong %inline.content; >
<!ATTLIST strong %inline.attr; >
<!ELEMENT cite %inline.content; >
<!ATTLIST cite %inline.attr; >
<!ELEMENT q %inline.content; >
<!ATTLIST q %inline.attr; >

Parameter-Entitäten darf man mehrfach deklarieren, sofern das passiert, hat die erste Deklaration in der internen Teilmenge Vorrang vor dem Rest, ist diese nicht vorhanden, hat die erste Deklaration in der externen Teilmenge Vorrang vor dem Rest. Das ermöglicht es etwa recht einfach, eine Änderung in der internen Teilmenge vorzunehmen, etwa ein Attribut zu ergänzen.

Ähnlich wie bei den Abkürzungen für XML-Dateien kann man auch Parameter-Entitäten in externe Dateien auslagern, das geht mit entsprechender Syntax, das eignet sich sogar, um komplette Teile einer DTD auszulagern:

<!ENTITY % untermenge1 SYSTEM "untermenge1.dtd">
%untermenge1;

Entsprechend kann man natürlich auch das Schlüsselwort 'PUBLIC' wählen, wenn die so ausgelagerte Parameter-Entität von allgemeiner Bedeutung ist:

<!ENTITY % untermenge1 PUBLIC "WikiBook Markup Language Modul 1" "wbml_1.dtd">
%untermenge1;

Notations-Deklaration Bearbeiten

Notationen wurden bereits kurz erwähnt. Sie dienen unter anderem dazu, eigene Schlüsselwörter zu definieren, die über das hinausgehen, was etwa sonst als vorgegebene Werte von Attributen notiert werden könnte - Einschränkungen der Namensproduktion müssen nicht für Attributwere gelten, gibt man diese aber in der DTD explizit als Alternative von Zeichenfolgen an, gibt es diese Einschränkung. Um also allgemeiner zu notieren, kann mit einer Notations-Deklaration eine nahezu beliebige Zeichenfolge vorgegeben werden.

Eine Notation ähnelt also einem Alias, einem Ersatz für die eigentliche Zeichenfolge.

Die Notations-Deklaration beginnt mit '<!NOTATION ' dann folgt der Name des Alias, dann folgt nach einem Leerzeichen eines der Schlüsselwörter 'SYSTEM' oder 'PUBLIC'. Im Falle von 'SYSTEM' folgt darauf nach einem Leerzeichen die gewünschte Zeichenfolge in Anführungszeichen. Die Deklartion schließt wie immer mit '>'

Beispiel:

<!NOTATION svg SYSTEM "image/svg+xml">

Als Attributwert verwendet man das dann wie folgt (vergleiche auch das entsprechende Beispiel im Abschnitt zur Deklaration von Attributlisten):

<!ELEMENT bild >
<!NOTATION svg SYSTEM "image/svg+xml">
<!NOTATION png SYSTEM "image/png">
<!NOTATION jpeg SYSTEM "image/jpeg">
<!ATTLIST bild quelle CDATA #REQUIRED
               alternativtext CDATA #REQUIRED
               höhe CDATA "100%"
               breite CDATA "100%"
               typ NOTATION (svg | png | jpeg ) #REQUIRED
               frag ID #IMPLIED
               ref IDREF #IMPLIED
               reftext CDATA #IMPLIED
>

Entsprechend kann man das Schlüselwort 'PUBLIC' verwenden.

<!NOTATION svg PUBLIC "image/svg+xml">

Man kann aber auch wie bei anderen Deklarationen, die 'PUBLIC' verwenden, eine beschreibende und eine referenzierende Zeichenkette angeben:

<!NOTATION svg PUBLIC "W3C/SVG" "http://www.w3.org/TR/2011/REC-SVG11-20110816/mimereg.html">

Bei Entitätendeklarationen ist eine Notation ebenfalls wie bereits diskutiert nutzbar, um die Entität als nicht zu interpretierender Inhalt zu kennzeichnen:

<!ELEMENT bild EMPTY>
<!ATTLIST bild quelle ENTITY #REQUIRED>
<!ENTITY kreise SYSTEM "Bild.jpg" NDATA jpeg />
<!NOTATION jpeg SYSTEM "image/jpeg">

Konditionale Bereiche Bearbeiten

Es ist auch möglich, Teile einer DTD so zu kennzeichnen, dass diese entweder explizit zur DTD gehören oder aber ähnlich ignoriert werden wie ein Kommentar. Der wesentliche Unterschiede zu einem Kommentar ist besonders bei modularen DTDs relevant, wenn diese Konstruktion zusammen mit redefinierten Parameter-Entitäten verwendet wird. So kann man je nachdem, in welchem Zusammenhang ein Modul verwendet wird, recht einfach Teile davon einbinden oder explizit ausschließen, je nachdem, auf welchen Wert man die zugehörige Parameter-Entitäten setzt.

Die eigentliche Syntax sieht wie folgt aus:

<![IGNORE [%irgendeineDeklaration1;]]>
<![INCLUDE [%irgendeineDeklaration2;]]>

Dabei stehen '%irgendeineDeklaration1;' und '%irgendeineDeklaration2;' für irgendwelche Deklarationsinhalte, die auch explizit notiert werden können, nicht unbedingt als Parameter-Entität. Um in einem Modul umzuschalten, notiert man etwa wie folgt:

<![%kond1;[%irgendeineDeklaration1;]]>
<![%kond2;[%irgendeineDeklaration2;]]>

Nun kann man dies etwa als externe Entität einbinden und dann die Parameter-Entitäten nach Bedarf festlegen, auch in der internen Teilmenge der DTD:

<!ENTITY % kond1 "INCLUDE">
<!ENTITY % kond2 "IGNORE">

Je nachdem, ob man also 'INCLUDE' oder 'IGNORE' festlegt, wird der jeweilige Teil entweder verwendet oder nicht.

Elemente oder Attribute? Bearbeiten

Ist man Autor eines XML-Formats, kann man sich überlegen, ob man Attribute intensiv nutzt oder doch eher versucht, möglichst viel mit Elementen und Unterelementen zu formulieren. Attribute kann man immer nur einmal pro Element setzen, Unterelemente kann man nach Bedarf erlauben. Attributwerte können nur den sehr eingeschränkten Inhalt von interpretiertem Text haben, Elemente können nach Bedarf auch andere Elemente als Inhalt haben, der Inhalt kann also weiter strukturiert werden, dafür ist die Notation von Attributwerten deutlich kompakter durch den Verzicht auf weitere Markierungen. So pflegt man etwa bei Listen in Attributwerten diese voneinander mit Leerzeichen oder Kommata zu separieren, manchmal auch mit Semikola, es braucht also nur ein Zeichen, bei einer Element-Syntax sind es pro nicht leerem Listenelement mindestens sieben Zeichen. Wo es also drauf ankommt, Speicherplatz zu sparen, lohnt es sich zu überlegen, ob man nicht lieber die zu einem Element assoziierte Information in einem Attribut unterbringt als in weiteren Unterelementen. Ist der Inhalt aber komplizierter und ist oft weiter zu strukturieren oder man will einfach und unabhängig etwa über den XML-DOM darauf zugreifen können und Teile unabhängig voneinander manipulieren oder auslesen, so ist eine Notation mit Elementen viel effizienter. (DOM: Dokument-Objekt-Modell - Dokumentstrukturen werden intern in einem Programm als Objekte repräsentiert, auf welche zugegriffen werden kann, um sie einzeln auszulesen oder zu manipulieren oder zu transformieren.)

Ein typisches Beispiel solch einer Abwägung liegt etwa bei SVG vor, wenn beim Element path der Pfad einer zu präsentierenden graphische Form anzugeben ist. Die Lösung von SVG ist, auch weil solch Pfad-Informationen bei Beispielen aus der Praxis oft sehr umfangreich sind, mit einer möglichst kompakten Notation mit möglichst wenig Speicherplatz auszukommen, dafür ist das Ergebnis etwas kryptisch bis gewöhnungsbedürftig und nicht auf den ersten Blick intuitiv zu verstehen, Beispiel:

<path
d="M600,0C1200,0 970.82,-705.34 485.41,-352.67S
0,0 185.41,-570.63-370.82,-1141.27-185.41,-570.63
0,0-485.41,-352.67-1200,0-600,0
0,0-485.41,352.67-370.82,1141.27-185.41,570.63
0,0 185.41,570.63 970.82,705.34 485.41,352.67
0,0 600,0Z" />

Dies ist eine geschlossene kubische Kurve mit fünfzähliger Drehsymmetrie und entsprechender Spiegelsymmetrie. Die Buchstaben im Wert des Attributes d sind Kommandos, welcher Kurventyp zu malen ist, die in diesem Beispiel mit Komma separierten Zahlenpaare sind Koordinaten. Nun kann man in SVG die meisten Attribute zum Beispiel per deklarativer Animation manipulieren, also zeitabhängig ändern. Um eine Koordinate zu ändern, muß hier dann der komplette Attributwert manipuliert werden. Und die Koordinaten sind nicht unabhängig voneinander veränderbar/animierbar. Hätte man nun für jedes Kommando oder gar jedes Koordinatenpaar oder gar jede Koordinate ein eigenes Element zur Verfügung, wäre es möglich, beziehungsweise erforderlich, jedes einzeln und unabhängig zu ändern oder zu animieren. Das ist gut, wenn man wirklich jedes einzeln und unabhängig ändern oder animieren will, aufwendig, wenn man doch den gesamten Pfad ändern will. SVG bietet nun wiederum eigene DOM-Methoden an, um den Wert des Attributes d zu analysieren und zu manipulieren, bietet aber keine Methode an, um deklarativ (also per XML-Syntax ohne zusätzliches Programm oder Skript) auf einzelne Strukturen des Attributwertes zuzugreifen.

Etwa bei dem Format MathML für mathematische Inhalte ist man den Weg gegangen, formal perfekt und mathematisch präzise für jede Operation und jede mathematische Struktur einer mathematischen Formel ein passendes Element zu wählen, statt Vieles auch einfach als interpretierten Text in einem Element notieren zu können. Dies hat zur Folge, dass das Format etwas sperrig mit einem einfachen Texteditor zu verwenden ist. Die vielen verschachtelten Elemente selbst für recht einfache Formeln sind aber vielleicht auch ein Grund dafür, dass das Format nur sehr zögerlich und meist unvollständig in gängige Darstellungsprogramme implementiert wurde. Die Komplexität solcher Dokumente oder Dokumentfragmente mit sehr vielen Elementen macht das zugehörige Dokument-Objekt-Modell im Darstellungsprogramm sehr umfangreich, es braucht also ziemlich viel Rechenzeit und Speicher, um solch ein Fragment darzustellen, mehr noch, um es über das DOM zu manipulieren, wobei das bei mathematischen Formeln eventuell nicht die typische Anwendung ist, eine Repräsentation über ein DOM also oft gar nicht notwendig sein wird, weil das aber das pauschale Vorgehen der Programme für XML-Formate wie auch HTML-Markierungssuppe ist, ist man da kaum bereit, diese Programme für einzelne Formate zu optimieren.

Praktisch ist also bei der Entwicklung von Formaten sorgfältig abzuwägen, welche Information man in Elementen unterbringt, welche in Attributen. Dazu lohnt es auch, eine Prognose über die Zielgruppen des Formates zu erstellen:
Sollen Dokumente einfach mit Texteditoren zu erstellen sein?
Sollen Dokumente primär einfach mit Programmen auslesbar sein?
Sollen Dokumente inhaltlich sehr flexibel, einfach und tief manipulierbar sein?
Soll das allgemeine XML-DOM ausreichen, um Dokumentinhalte zu manipulieren oder ist eine DOM-Repräsentation/Manipulation gar nicht notwendig oder relevant?
Handelt es sich eher um narrative Inhalte, die nach der Erstellung nicht mehr manipuliert werden, wo man aber eine semantisch reichhaltige Kollektion von Elementnamen braucht?
Ist es notwendig, dass Dokumente sehr schnell oder nur mit sehr einfachen Programmen einem ungeduldigen menschlichen Publikum präsentiert werden müssen?
Oder sind die Konsumenten nur Programme, die automatisch und zuverlässig maschinenlesbare Daten extrahieren müssen, um sie anderweitig zu verwenden?