DTDs und XSDs verstehen - Teil 2

15.08.2006 von Martin Kuppinger
Wie die DTDs, die im ersten Teil der Artikelserie im Mittelpunkt standen, sind auch XSDs (XML Schema Definitions) ein Ansatz für die Beschreibung der Datenstrukturen von XML-Dateien. Der Artikel erläutert die Grundstruktur und die wichtigsten Elemente in diesen Dateien, auch für die der Version Lotus Domino 7.0.

Document Type Definitions, kurz DTDs, sind der Standardansatz bis Domino 6.x. Ab der Version 7.x werden auch XSDs unterstützt.

XSDs sind selbst wieder XML-Dateien. Mit einer XML-Datei wird also die Struktur anderer XML-Dateien beschrieben. Dieses Verfahren ist grundsätzlich sinnvoll, weil man sich damit eigentlich nur mit XML auskennen muss, um auch eine XSD „lesen“ zu können.

Der erste Eintrag in einer solchen Datei ist damit logischerweise der Verweis auf die verwendete XML-Version, also

<?xml version="1.0" encoding="UTF-8"?>

Anschließend erfolgt mit

<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.lotus.com/dxl"
targetNamespace="http://www.lotus.com/dxl"
elementFormDefault="qualified">

die Festlegung der Namespaces, die verwendet werden. Neben dem Standard ist das in diesem Fall noch die Definition von Lotus für DXL. Weiter geht es mit einer Liste der zulässigen Root- Elemente – also der Elemente auf oberster Ebene – in den beschriebenen XML-Dokumenten. Bei der Domino-XSD sieht das – in einem Ausschnitt – wie folgt aus:

<xsd:element name="note" type="note"/>
<xsd:element name="document" type="document"/>
<xsd:element name="form" type="form"/>
<xsd:element name="helpaboutdocument" type="helpaboutdocument"/>
<xsd:element name="helpusingdocument" type="helpusingdocument"/>
<xsd:element name="imageresource" type="imageresource"/>
<xsd:element name="sharedfield" type="sharedfield"/>

Hier werden Elemente wie document oder form zunächst grundlegend definiert. Neben dieser normalen Festlegung von Elementen können auch Gruppen definiert werden, wie beispielsweise bei den verschiedenen Arten von Notes:

<xsd:group name="note.types">
<xsd:choice>
<xsd:element name="note"
type="note"/>
<xsd:element name="document" type=" document"/>
<xsd:element name="profiledocument"
type="profiledocument"/>
<xsd:group ref="design.elements"/>
</xsd:choice>
</xsd:group>

Auswahl innerhalb einer Gruppe

Innerhalb einer Gruppe gibt es immer eine Auswahl (choice), was bedeutet, dass eines der folgenden Elemente verwendet werden muss. Ein weiteres Element bei der Beschreibung von Dateien sind komplexe Elemente, die wie folgt definiert werden:

<xsd:complexType name="created">
<xsd:sequence>
<xsd:element name="datetime"
type="datetime"/>
</xsd:sequence>
</xsd:complexType>

In diesem einfachen Beispiel wird eine Sequenz verwendet, die wiederum auf ein bestimmtes Element mit einem bestimmten Datentyp verweist. Der spezielle Datentyp created besteht also aus einem Datumseintrag. Die Definition von Datentypen kann aber auch anders aussehen:

<xsd:complexType name="databaseinfo">
<xsd:sequence>
<xsd:element name="datamodified"
type="datamodified" minOccurs="0" maxOccurs="1"/>
<xsd:element name="designmodified"
type="designmodified" minOccurs="0" maxOccurs="1"/>
<xsd:element name="created"
<xsd:element name="modified"
type="modified" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="dbid" type="noteshex"
use="optional"/>
<xsd:attribute name="replicaid"
type="noteshex" use="optional"/>
<xsd:attribute name="odsversion"
type="xsd:integer" use="optional"/>
<xsd:attribute name="diskspace"
type="xsd:integer" use="optional"/>
<xsd:attribute name="numberofdocuments"
type="xsd:integer" use="optional"/>
<xsd:attribute name="percentused"
type="xsd:float" use="optional"/>
</xsd:complexType>

Hier können entweder eine Sequenz aus mehreren Elementen oder (in diesem Fall optionale) Attribute verwendet werden. Bei den Sequenzen sind insbesondere die Festlegungen für das minimale und maximale Auftreten von Bedeutung, mit denen festgelegt wird, ob diese vorkommen müssen oder nicht und ob sie mehrfach vorkommen dürfen. In diesem Fall wird bei maxOccurs der Wert unbounded gesetzt.

Standardwerte

Bei Attributen können auch Standardwerte angegeben werden, wie in diesem Beispiel:

<xsd:attribute name="logtransactions"
type="xsd:boolean" use="optional" default="true"/>

Neben Werten wie true und false lassen sich auch andere Werte vorgeben. Dabei wird in der Regel mit einfachen Zeichenketten gearbeitet. Eine andere Art von Typdefinitionen sind die einfachen Datentypen, die beispielsweise in der Form

<xsd:simpleType name="acl.levels">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="noaccess"/>
<xsd:enumeration value="depositor"/>
<xsd:enumeration value="reader"/>
<xsd:enumeration value="author"/>
<xsd:enumeration value="editor"/>
<xsd:enumeration value="designer"/>
<xsd:enumeration value="manager"/>
</xsd:restriction>
</xsd:simpleType>

erstellt werden. Hier wird ein Typ erstellt, der nur aus einem Wert besteht, wobei es sich um Zeichenketten handelt. Aus den angegebenen Zeichenketten kann eine ausgewählt werden.

Interessant sind auch die Attributgruppen. Sie fassen mehrere Attribute zusammen, wie beispielsweise bei

<xsd:attributeGroup name="launch.common.attrs">
<xsd:attribute name="whenopened" use="optional">
<xsd:simpleType>
<xsd:restriction
base="xsd:string">
<xsd:enumeration
value="openaboutdocument"/>
<xsd:enumeration
value="openframeset"/>
<xsd:enumeration
value="opennavigatorinwindow"/>
<xsd:enumeration
value="openfirstdoclink"/>
<xsd:enumeration
value="restorelastview"/>
<xsd:enumeration
value="opennavigator"/>
<xsd:enumeration
value="openfirstaboutattachment"/>
<xsd:enumeration
value="usenotesoptions"/>
<xsd:enumeration
value="openpage"/>
<xsd:enumeration
value="openspecifieddoclink"/>
<xsd:enumeration
value="openfirstdocumentinview"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="frameset"
type="xsd:string" use="optional"/>
<xsd:attribute name="navigator"
type="xsd:string" use="optional"/>
</xsd:attributeGroup>

Hier findet man sowohl einen einfachen Datentyp als auch zusätzliche Attribute, die mit diesem zusammen verwendet werden müssen. Attributgruppen werden verwendet, wenn bestimmte Attribute immer gemeinsam vorkommen. Interessant ist auch die Referenzierung im folgenden (gekürzten) Beispiel:

<xsd:sequence>
<xsd:group ref="named.design.note.prolog"/>
<xsd:element name="code" type="code" minOccurs="
0" maxOccurs="1"/>
<xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element name="frameset"
type="frameset"/>
<xsd:element name="frame"
type="frame"/>
</xsd:choice>
<xsd:group ref="note.epilog"/>
</xsd:sequence>
<xsd:attributeGroup
ref="named.design.note.attrs"/>
<xsd:attribute name="rows" type="xsd:string"
use="optional"/>

In diesem Fall wird beispielsweise auf name.design. note.prolog und auf note.epilog sowie auf named. design.note.attrs Bezug genommen. Diese Informationen sind an anderer Stelle als Gruppen oder Attributgruppen in der Spezifikation der XSD konfiguriert worden.

Mit diesen Definitionen und einigen wenigen zusätzlichen Varianten wird die gesamte Datenstruktur beschrieben. Dabei wird von den Root- Elementen ausgegangen, die weiter in untergeordnete Elemente und Attribute zerlegt werden,bis die gesamte Struktur der XML-Datei beschrieben ist. Das Konzept ist im Grundsatz relativ einfach, weil man mit einer sehr geringen Zahl an Grundstrukturen auskommt und beispielsweise keine speziellen Zeichen benötigt, um die zulässige Anzahl von Attributen zu beschreiben. Stattdessen wird einfach die minimale und maximale Zahl definiert.

Diese relative Einfachheit im Vergleich zu DTDs machen XSDs zum bevorzugten Ansatz, wenn die Strukturen von XML-Dokumenten beschrieben werden sollen.