Sql-und-Xml - Home

Xml lernen

Die document type definition zur Validierung eigener Xml-Dokumente

Vorbemerkung: Um die folgenden Beispiele praktisch anwenden zu können, benötigen Sie einen validierenden Parser. Falls Sie den Internet Explorer Version 6 nutzen oder sich bei einem InternetExplorer ab Version 5 die MSXML3 von Microsoft installiert haben, können Sie den Online-Xml-Trainer verwenden.

Soll das Xml-Dokument nicht nur wohlgeformt sein, sondern soll zusätzlich festgelegt werden, welche Elemente, Attribute und welche Schachtelungen erlaubt sind, so muß ein eigener Xml-Dokumenttyp beschrieben werden. Jeder dieser Dokumenttypen ist durch eine genau festgelegte Menge an Element-Typen und zugeordneten Attribut-Typen charakterisiert. Bei der Definition von jedem Element-Typ wird zusätzlich festgelegt, welche Typen von Unterelementen bzw. ob Text als Content dieses Elementtyps erlaubt ist. Eine solche Definition eines Dokument-Typs, eine eigene document type definition (DTD) deklariert also, welche zusätzlichen Einschränkungen ein bereits wohlgeformtes Xml-Dokument erfüllen muß, damit es zusätzlich als 'Dokument dieses Dokumenttyps' betrachtet werden darf. Eine DTD kann ferner Entity-Deklarationen enthalten. Diese kann man sich vorstellen als Funktionen oder Makros, die einen Wert, eine Zeichenfolge oder den Inhalt eines Dokuments zurückliefern und dessen Verwendung gestatten. Von Entities gibt es zwei Typen: Globale Entities können überall dort verwendet werden, wo gemischter Content, also #PCDATA zulässig ist. Parameter-Entities dienen als Makros innerhalb der externen DTD.

Damit muß einem Dokument eine DTD zugeordnet werden, dies ist auf vier verschiedene Arten möglich. Allen Arten gemeinsam ist, daß das Xml-Dokument einen Abschnitt enthält, der minimal wie folgt aussieht:
<!DOCTYPE QName

	... hier folgen weitere Festlegungen

>

<QName>

	... hier folgt der Dokumentinhalt

</QName>
QName ist sowohl der Name der DTD als auch der Name des Wurzel-Elements dieses Xml-Dokumentes. Bei QName handelt es sich um einen qualified Name, der entweder keinen Doppelpunkt enthält oder - im Sinne eines Namespaces - in Präfix und local part zerfällt, verbunden durch den Doppelpunkt.

Zuordnungsmöglichkeiten zwischen einem Dokument und seiner DTD

1. Interne DTD

Eine DTD kann zunächst innerhalb eines Xml-Dokuments erstellt werden. Dann gilt diese DTD jedoch auch nur für dieses Dokument, so daß für jedes Xml-Dokument eine eigene DTD erstellt werden muß. Um zu lernen, wie Element- und Attributtypen definiert werden, genügt diese Version.
Beispiel:
<?xml version='1.0'?>
<!DOCTYPE small-sample
	[
	<!ELEMENT small-sample EMPTY>
]>

<small-sample></small-sample>
Die Definitionen werden innerhalb des obigen Rahmens notiert und zusätzlich in eckige Klammern eingeschlossen.

2. Verweis auf eine externe DTD in einer Datei

Die meistens verwendete Version für selbsterstellte große DTD's, auf die viele Dokumente aufbauen, besteht in der Erstellung einer externen DTD, die per Verweis eingebunden wird. Die externe DTD ist eine übliche Textdatei im Ansi- oder Unicode-Format.
<?xml version='1.0'?>
<!DOCTYPE firma-max-mustermann SYSTEM
	"http://www.sql-und-xml.de/xml-samples/firma-max-mustermann.dtd" >

<firma-max-mustermann>

	<!-- ... weitere Unterelemente und Content -->

</firma-max-mustermann>

Das Schlüsselwort SYSTEM fordert einen anschließenden Verweis auf eine URI, dies kann eine lokale oder eine per http referenzierte externe Datei sein. Diese enthält jene Angaben, welche bei der internen Definition in eckigen Klammern stehen. Die eingebundene externe DTD firma-max-mustermann.dtd definiert lediglich zwei Entities für das nächste Beispiel sowie das Wurzelelement.

3. Verweis auf eine externe DTD und lokale Definitionen

Eine erweiterte Technik besteht darin, einerseits eine externe DTD zu referenzieren und andererseits lokale Definitionen, etwa globale Entities, zu ergänzen, die speziell in diesem Xml-Dokument benötigt werden.
<?xml version='1.0'?>
<!DOCTYPE firma-max-mustermann SYSTEM
	"http://www.sql-und-xml.de/xml-samples/firma-max-mustermann.dtd"
	[
	<!ENTITY my-signatur "Max Mustermann" >

]>

<firma-max-mustermann>

	&gruss;

	<!-- ... weitere Unterelemente und Content -->

	&my-signatur;

</firma-max-mustermann>
Die Definition der Elemente wird aus der externen DTD firma-max-mustermann.dtd geholt. Diese enthält bereits zwei Entities. Die zweite Entity wird lokal redefiniert, so daß der lokal festgelegte Wert tatsächlich im Dokument sichtbar wird. Die externe Entity enthält das Copyright-Zeichen, in der lokalen Definition fehlt dieses, letztere wird angezeigt.
Man kann also Entities doppelt definieren, in der externen DTD sind sie bereits gültig. Im lokalen Dokument definiert man sie erneut und weist ihnen damit einen anderen Wert zu, dieser überschreibt den zunächst zugewiesenen Wert.

4. Verwendung eines PUBLIC - Identifiers

Die vierte Möglichkeit besteht darin, einen PUBLIC-Identifier, einen veröffentlichten und dem Parser bekannten Dokumenttyp zu verwenden.
<?xml version='1.0'?>

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

<html>

	<!-- hier folgt ein XHTML1.1 - konformes Xml-Dokument -->

</html>
Bei einigen weltweit bekannten und genutzten DTD existiert für diese eine eindeutige Bezeichnung, ein öffentlicher Identifier. Hier wäre es nicht sinnvoll, direkt die DTD anzugeben, so daß der Parser bei jedem Laden eines Html-Dokuments die gesamte DTD verarbeitet. Stattdessen wird dem Parser intern ein Modul mitgegeben, welches die DTD in einer bereits verarbeiteten Version enthalten dürfte. So muß nur noch geprüft werden, ob das aktuelle Dokument diese DTD erfüllt.
Ein solcher PUBLIC-Identifier wird direkt hinter dem Schlüsselwort PUBLIC notiert. Anschließend kann eine DTD direkt angegeben werden, dies ist jedoch nicht zwingend. Bei einem Identifier ist die Zeichenfolge strikt zu beachten.

Conditional Sections: Verwenden von INCLUDE und IGNORE

Die beiden Schlüsselwörter INCLUDE und IGNORE erlauben eine Art von Direktiven, wie man sie von Programmiersprachen her kennt. Allerdings können beide Schlüsselwörter nur in externen DTD's genutzt werden. Die direkte Verwendung erinnert an CDATA-Sections:
<![INCLUDE[

	<!-- Anweisungen, die einzuschliessen sind -->

]]>
IGNORE wird ebenso verwendet, schließt jedoch die festgelegten Anweisungen aus. Interessant wird diese Technik, falls man sie mit Entities kombiniert:
<!ENTITY experimental 'INCLUDE'>
<!ENTITY final 'IGNORE'>

<![%experimental;[
	<!ELEMENT program (internal-comments*, title, code, abstract)>
]]>

<![%final;[
	<!ELEMENT program (title, code, abstract)>
]]>
Entities können mit diesen Schlüsselwörtern belegt werden, so daß erst zur Analysezeit der INCLUDE-Block festgelegt wird. Im ersten Fall wird das Element 'program' mit zusätzlichen, nicht zur Veröffentlichung bestimmten Kommentaren ergänzt, im zweiten Fall hat das Element 'program' keine entsprechenden Unterelemente. Einfaches Vertauschen von 'experimental' und 'final' bei der Entity-Deklaration erzeugt einen veränderten Dokumenttyp und erzwingt das Entfernern aller Kommentare.
Da Entities im Xml-Dokument redefiniert werden können und diese die in der externen DTD deklarierten Werte überschreiben, läßt sich damit auch eine Veränderung der Namespace-Deklaration leicht erzeugen.

Nutzen einer DTD

Der Aufwand für die Erstellung einer DTD kann rasch einen größeren Umfang annehmen. Im folgenden finden Sie einige Hinweise, wann man eine DTD verwenden sollte bzw. wann sich der Aufwand für die Erstellung einer DTD nicht lohnt.

Mögliche Gründe für eine DTD

  • Projektdokumentation: Eine DTD dokumentiert die Struktur der Xml-Dokumente genauer, als dies aus dem jeweiligen Xml-Dokument hervorgeht. Man denke an Attribute, die genau einen Wert aus einer Liste annehmen dürfen - die Liste steht nur in der DTD, jedes Attribut kennt höchstens einen Wert.
  • Verwenden von Techniken, die zwingend eine DTD benötigen: Attribute mit Default-Werten, die im Xml-Dokument weggelassen werden können und vom Parser dennoch mit dem Default-Wert eingefügt werden. Verwenden von Attributen des Typs ID / IDREF usw. sowie von Auflistungstypen. Alle Entity-Typen können nur in einer DTD deklariert werden. Verwenden von INCLUDE / IGNORE.
  • Regelmäßige Erstellung großer Xml-Dokumente, welche denselben Regeln, damit derselben DTD genügen müssen. Werden wiederholt, womöglich von verschiedenen Personen, Xml-Dokumente erstellt, die zwingend gleichartig aufgebaut sein müssen, so ist die Erstellung und Pflege einer DTD Pflicht, gegen welche jedes Xml-Dokument validiert wird.
  • Wiederholtes Verarbeiten von Daten, die an anderer Stelle erstellt wurden: Jeder strukturierte Datenaustausch läßt sich über Xml abwickeln, ein Xml-Dokument kann per Mail empfangen oder vom Versender einfach zum Download auf einer Website bereitgestellt werden. Hier wird man die Anforderungen an die erhaltenen Dokumente nur selten ändern und sie in einer vielleicht über die eigene Domain veröffentlichten DTD festschreiben. Sowohl die Ersteller als auch die Empfänger der Xml-Dokumente können rasch prüfen, ob das versandte bzw. erhaltene Dokument der DTD genügt.
  • Weiterverarbeitung der Xml-Quelle mit XSLT: XSLT verwendet templates mit match-Attributen, die auf Xml-Elemente verweisen. Fehlt in einem Xml-Dokument ein Element, welchem im XSLT-Dokument ein template zugeordnet ist, so ist dies kein Fehler, es führt nicht zu einem Abbruch. Es wird lediglich das zugehörige template nicht beachtet und nicht ausgeführt. Damit können Schreibfehler im Xml-Dokument, bei welchen bsp. ein wichtiges Element sowohl beim Öffnen als auch beim Schließen konsistent anders notiert wurde, zu lückenhaften Ausgaben führen, sie stellen damit eine nur sehr schwer ermittelbare Fehlerquelle dar. Eine DTD kann dieses Problem vermeiden, da im Xml-Dokument nicht erlaubte Elementnamen sofort zu einem Abbruch führen.

Situationen, in welchen sich die Mühe für eine DTD nicht lohnt

  • Erstellen einer DTD, die nur für ein einziges Dokument benötigt wird. Eine DTD ist erst dann wirklich sinnvoll, wenn mehrere Dokumente basierend auf einer DTD erstellt werden. Ausnahme: Erstellen einer DTD zu Lernzwecken.
  • Zur Erarbeitung von XSLT: Für das Lernen von eXtensible Stylesheet Transformation Language, der Transformationssprache, mit der man ein Xml-Dokument in ein anderes Xml-Dokument oder in reinen Text transferieren kann, ist die Erstellung einer DTD für das Xml-Quelldokument nicht notwendig und auch nicht sinnvoll. XSLT kann jedes wohlgeformte XML-Dokument verarbeiten, die zusätzliche Validität der Xml-Quelle ist nicht notwendig. fehlt eine DTD, kann man dem Xml-Dokument rasch neue Elemente hinzufügen und die Auswirkungen auf das Transformationsergebnis testen, ohne die Validität des Dokuments zu gefährden.
  • Nur eine Person arbeitet mit den Xml-Dokumenten und fügt Elemente und Attribute ad hoc hinzu. Auf eine Dokumentation wird derzeit verzichtet, da sich die Struktur der Xml-Dokumente ständig ändert.

© 2003-2016 Jürgen Auer, Berlin.