Valide XML-Dokumente gegen eine Document-Type-Definition erstellen
https://bildung.social/@oerinformatik/111970765687640258
https://oer-informatik.de/xml-dtd
tl/dr; (ca. 10 min Lesezeit): Alle XML-Dokumente müssen wohlgeformt sein, also den allgemeinen XML-Regeln genügen. Mit Hilfe der DocumentTypeDefinition oder mit XML-Schema können aber darüber hinaus spezifische Regeln an die Abfolge von Elementen und Attributen gestellt werden. Ein XML-Dokument, das solchen Regeln folgt, wird als valide bezeichnet. Dieser Artikel beschreibt die Grundlagen zur Erstellung einer Document-Type-Definition. (Zuletzt geändert am 10.03.2024)
Dieser Artikel ist Bestandteil einer Serie zu den XML-Grundlagen:
Teil 1: XML-Grundlagen und Wohlgeformtheit: Hierarchische Daten mit XML speichern mit zugehörigen Übungsaufgaben
Teil 2: XML-Dokumente gegen eine Document-Type-Definition validieren mit zugehörigen Übungsaufgaben
Teil 4: Die Struktur von XML-Dokumente gegen ein XSD-Schema validieren
Teil 5: Datentypen-Definitionen eines XML-Schema zur Validierung nutzen
Nach Durchlesen des Artikels kann ich…
… eine Document-Type-Definition inline oder extern einbinden,
… Elementefolgen, Optionalitäten und Häufigkeit mit DTD definieren,
… festlegen, ob ein Element über Inhalte verfügen muss, und ob dies Unterelemente oder Text ist,
… definieren, ob ein Element über Attribute verfügt und welchen Typs die Inhalte sind.
Festlegen, in welcher Reihenfolge und Anzahl XML-Elemente aufeinander folgen
Mithilfe einer Document-Type-Definition (DTD) können Regeln an den Aufbau und die Abfolge von Elementen und Attributen getroffen werden. DTDs lassen sich intern in XML-Dokumente integrieren (siehe folgendes Beispiel) oder in einer gesonderten Datei verwalten (Beispiele unten).
Wir betrachten den Aufbau einer DTD für eine _XML-Datei an folgendem Beispiel (ab Zeile 2 beginnt die DTD, mit <adressen> beginnt das eigentliche XML-Rootelement):
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE adressen [
<!ELEMENT adressen (adresse)+ >
<!ELEMENT adresse (vorname, nachname, telefon?, kommentar?, id?)>
<!ELEMENT vorname (#PCDATA)>
<!ELEMENT nachname (#PCDATA)>
<!ELEMENT telefon (mobil|festnetz)*>
<!ELEMENT mobil (#PCDATA)>
<!ELEMENT festnetz (#PCDATA)>
<!ELEMENT id EMPTY>
<!ATTLIST id
personal_id CDATA #REQUIRED
mitarbeiter_id CDATA #IMPLIED
exists CDATA #FIXED "true" >
<!ELEMENT kommentar ANY>
]>
<adressen>
<adresse>
<vorname>Max</vorname>
<nachname>Mustermann</nachname>
<telefon>
<mobil>01234/567890</mobil>
</telefon>
<kommentar>
Wohnt bei <vorname>Peter</vorname>
</kommentar>
<id personal_id="12345" mitarbeiter_id="6789"/>
</adresse>
</adressen>Die interne DTD wird umschlossen von <!DOCTYPE ... [ und ]>, wobei anstelle der Punkte der Name des Root-Elements steht.
Darauf folgt die Beschreibung der Elemente mit Elementeinhalt nach dem Muster:
Die Kindelemente können dabei in Klammern (...) als Gruppen zusammengefasst und mit Konnektoren als Alternative (|) oder als Sequenz (,) formuliert werden:
| Beispiel | Konnektor | Beschreibung |
|---|---|---|
<!ELEMENT adresse (vorname, nachname)> |
, |
Liste (wird gefolgt von) |
<!ELEMENT telefon (mobil|festnetz)> |
| |
Alternative (entweder / oder) |
Für jede Gruppe und für jedes Kindelement kann eine Quantität angegeben werden:
| Beispiel | Quantität | Beschreibung |
|---|---|---|
<!ELEMENT adresse (telefon?)> |
? |
telefon ist in adresse optional (kein- oder einmal) |
<!ELEMENT adressen (adresse)+ > |
+ |
adresse kommt in adressen ein oder mehrmals vor |
<!ELEMENT telefon (mobil|festnetz)*> |
* |
die Gruppe kommt in telefon einmal oder mehrmals vor |
<!ELEMENT adresse (vorname, nachname)> |
nichts | vorname und nachname müssen in adresse genau einmal vorkommen |
Neben Kindelementen kann für ein Element auch noch festgelegt werden, dass es leer ist (EMPTY), beliebigen Inhalt haben kann (ANY) oder parsbaren Text enthält (PCDATA):
| Beispiel | Quantität | Beschreibung |
|---|---|---|
<!ELEMENT vorname #PCDATA> |
PCDATA |
vorname darf nur parsbaren Text enthalten (parsed character data) |
<!ELEMENT kommentar ANY> |
ANY |
kommentar darf beliebige Kindelemente oder Daten enthalten |
<!ELEMENT id EMPTY> |
EMPTY |
id darf keinen Elementeinhalt enthalten, ist also ein leeres Element (lediglich Attribute, siehe unten) |
Die obigen Beispiele können natürlich auch kombiniert werden, man spricht dann von Mixed Contend:
| Beispiel | Beschreibung |
|---|---|
<!ELEMENT vorname (#PCDATA | künstlername | ordensname)*> |
wichtig: #PCDATA muss als erstes genannt sein, die Reihenfolge der nachfolgenden Elemente kann nicht festgelegt werden und am Ende muss der Asterisk stehen |
Auch für Attribute können unterschiedliche Festlegungen getroffen werden, beispielsweise können besondere Typen angegeben werden:
| Beispiel | Typ | Beschreibung |
|---|---|---|
<!ATTLIST id personal_id CDATA> |
CDATA |
personal_id enthält Text inkl. aller Whitespaces - das ist der Standardfallwichtig: bei Attributen wird CDATA verwendet, bei Elementinhalten PCDATA |
<!ATTLIST id personal_id ID> |
ID |
Der Wert eines ID-Attributs muss das Element eindeutig identifizieren und einzigartig sein. Außerdem muss der Wert den Namensregeln für Elemente entsprechen (also “1” ist unzulässig). Es darf nur ein ID Attribut je Element gebe. |
<!ATTLIST id aktiv (ja | nein)> |
ENUM Aufzählung |
Der Wert eines Aufzählungs-Attributs einem der genannten Werte entsprechen (hier: ja oder nein). |
<!ATTLIST id personal_id NMTOKEN> |
NMTOKEN |
Bei Attributen vom Typ NMTOKEN werden im Gegensatz zu CDATA beim Parsen beispielsweise Whitespaces entfernt. Details siehe Nr. 3.3.3 im Standard |
Es gibt eine Reihe weiterer Attributtypen, die sich in der Spezifikation nachlesen lassen. Darüber hinaus können auch Optionalitäten und Defaultwerte angegeben werden. Die Defaultwerte folgend der Optionalität in Anführungszeichen (siehe Tabelle bei #FIXED):
| Beispiel | Optionalität | Beschreibung |
|---|---|---|
<!ATTLIST id personal_id CDATA #REQUIRED> |
#REQUIRED |
Ein Attribut personal_id ist erforderlich |
<!ATTLIST id mitarbeiter_id CDATA #IMPLIED> |
#IMPLIED |
das Attribut ist optional |
<!ATTLIST id exists CDATA #FIXED "true"> |
#FIXED defaultwert |
Der Attributwert darf hier nur der Defaultwert sein (Beispiel: id muss “true” sein). Bei einem anderen Wert validiert das Dokument nicht, bei einem fehlenden Wert wird beim Parsen id="true" ergänzt |
Die wesentlichen Bestandteile einer DTD für unser Beispiel habe ich hier nochmal annotiert:

Externe DTD
Da die Document Type Definition häufig einen Standard festlegt, über den Systeme miteinander XML-Dokumente austauschen, wird sie häufig nicht innerhalb des XML-Dokuments übermittelt, sondern als Link veröffentlicht (oder als lokale Datei), die dann im Dokument referenziert wird:
Webservices zur Validierung
Natürlich überprüft niemand von Hand, ob eine XML-Datei gegen eine DTD valide ist. Dafür gibt es Parser für alle Programmiersprachen. Ein paar Beispiele für Webservices, die das übernehmen finden sich hier:
Links und weitere Informationen
Infos von w3schools zu XML
Hinweis zur Nachnutzung als Open Educational Resource (OER)
Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Valide XML-Dokumente gegen eine Document-Type-Definition erstellen” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/xml-dtd veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/datenformate/xml. Stand: 10.03.2024.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]
