|
Übersicht: Datentypen
Einführung
Das Fehlen von unterschiedlichen Datentypen ist einer der Hauptkritikpunkte an DTDs. Informationen können nur als Zeichenketten
deklariert werden, genauere Einteilungen sind mit DTDs nicht möglich.
Alle bisher gezeigten Beispiele verwendeten als Datentypen für Elemente bzw. Attribute ebenfalls nur Zeichenketten,
die in einem W3C Schema durch eine Typ Definition: type="xs:string" und in Relax NG durch das <text/>-Muster
festgelegt wurden. W3C Schema und Relax NG bieten dem Anwender aber deutlich mehr Möglichkeiten, den Wertebereich von Elementen einzuschränken.
Dieser Vorteil gegenüber DTDs macht sich vor allem bei datenorientieren XML-Dokumenten bemerkbar. Die Daten-Validierung muss jetzt
nicht mehr durch das Programm erfolgen, sondern kann bereits im XML-Prozessor selbst implementiert sein, so dass der Anwender davon befreit wird.
Außerdem kommt die Daten-Typisierung natürlich auch der Integrität der Daten zugute.
In diesem Kapitel werden die unterschiedlichen Ansätze der Integration von Datentypen besprochen und dabei die wichtigsten Typen kurz vorgestellt.
|
|
W3C Schema Datentypen
Die W3C Schema Sprache umfaßt in der aktuellen Version knapp 50 verschiedene Datentypen. 19 von ihnen bilden die Klasse der primitiven
eingebauten Datentypen (build-in primitive types), zu denen beispielsweise string, boolean, date oder decimal zählen.
Alle anderen Typen (normalizedString, integer, byte, ...) sind von den primitiven abgeleitet und bilden die
Klasse der build-in derived types.
Die primitiven Datentypen stehen dabei in keiner Beziehung zueinander und bilden komplett unterschiedliche Wertebereich ab. Die abgeleiteten Typen
begrenzen hingegen den Wertebereich eines primitiven Typen, stehen also mit ihm in direkter Beziehung und wurden eingeführt, um häufig
genutzte Fälle abzudecken und damit die Anwenderfreundlichkeit zu erhöhen.
|
Abbildung 3: W3C Schema Datentyp Hierarchie |
Die eingebauten Datentypen können direkt in einer Element oder Attribut Deklaration verwendet werden.
1) <xs:attribute name="available" type="xs:boolean"/>
2) <xs:element name="isbn" type="xs:unsignedLong"/>
|
Das available-Attribut (1) eines Buches zeigt an, ob ein Buch zur Ausleihe bereit steht oder nicht.
Es kann also nur zwei sinnvolle, unterschiedliche Werte annehmen. Sein Typ wird daher auf einen boolschen Wert (true/false
bzw. 0/1) anstatt des bisher eingesetzten xs:string beschränkt.
1) <book id="..." available="xyz">
2) <isbn>9876543210</isbn>
3) <isbn>QWERTZ3210</isbn>
4) <isbn>12345</isbn>
5) ...
6) </book>
|
Beim Validieren eines Instanz-Dokuments kann der ungültige available-Wert (1) jetzt erkannt werden.
Eine ISBN Nummer besteht hingegen nur aus Ziffern, so dass sich eine Einschränkung auf den Bereich der positiven ganzen Zahlen
(xs:unsignedLong) anbietet. Sollte in einer ISBN Nummer ein Buchstabe enthalten sein (3), kann ein
validierender Parser diesen Fehler erkennen. Eine zweite Anforderung an ISBN Nummern kann jedoch nicht durch den unsignedLong-Typ
abgedeckt werden, eine Nummer muss immer aus exakt 10 Ziffern bestehen. Zeile 4 wäre mit dieser Schema-Definition für einen Parser aber auch
noch eine korrekte ISBN Nummer.
Dieses Problem kann in einem W3C Schema durch die Definition eigener, auf die Bedürfnisse zugeschnittener, Datentypen gelöst werden.
1) <xs:simpleType name="myUnsignedLong">
2) <xs:restriction base="xs:unsignedLong">
3) <xs:minInclusive value="1000000000"/>
4) <xs:maxInclusive value="9999999999"/>
5) </xs:restriction>
6) </xs:simpleType>
|
Als Basis dient der eingebaute Datentyp xs:unsignedLong (2), der mit Hilfe von Restriktionen (3), so genannten Fassetten, angepaßt wird.
Das Beispiel erzeugt einen Datentypen myUnsignedLong dessen Werte nur zwischen 1000000000 und 9999999999 liegen dürfen und
somit exakt 10 Ziffern enthalten.
Für die eingebauten Datentypen existieren eine Vielzahl von Fassetten die je nach Anforderung verwendet werden können. Die vollständige
Liste ist in der W3C Schema Spezifikation zu finden.
Zwei sehr wichtige und interessante Fassetten sind die Aufzählung und die Liste.
1) <xs:simpleType name="isbn">
2) <xs:restriction base="xs:unsignedLong">
3) <xs:enumeration value="1000000000"/>
4) <xs:enumeration value="2643857021"/>
5) <xs:enumeratin value="9999999999"/>
6) </xs:restriction>
7) </xs:simpleType>
|
Über eine Aufzählung ist die explizite Angabe der erlaubten Werte (3,4,5) für ein Element möglich, alle weiteren ISBN Nummern
würden in dem Beispiel nicht akzeptiert werden.
01) <xs:simpleType name="isbnListe">
02) <xs:list itemType="isbn"/>
03) </xs:simpleType>
04) <xs:simpleType name="zweiIsbnNummern">
05) <xs:restriction base="isbnListe">
06) <xs:length value="2"/>
07) </xs:restriction>
08) </xs:simpleType>
09)
10) <zweiIsbnNummern>1000000000 2643857021</zweiIsbnNummern>
11) <zweiIsbnNummern>1000000000 8888888888</zweiIsbnNummern>
|
Mit Listen (2) können mehrere Werte, durch Leerzeichen getrennt, innerhalb eines Elements dargestellt werden. Es sind dabei natürlich
auch weitere Einschränkungen der Liste (6) über andere Fassetten erlaubt.
Das erste Instanz-Beispiel (10) wäre gültig, das Zweite (11) hingegen nicht, da die Zahl 8888888888 kein
Wert der definierten Aufzählung isbn ist.
Die mächtigste Fassette ist aber das xs:pattern-Tag (3). Es erlaubt die Einschränkung des Bereiches über einen
regulären Ausdruck.
Die ISBN Nummer kann mit xs:pattern sehr kompakt auf die folgende Weise definiert werden:
1) <xs:simpleType name="isbnType">
2) <xs:restriction base="xs:string">
3) <xs:pattern value="[0-9]{10}"/>
4) </xs:restriction>
5) </xs:simpleType>
|
|
|
Relax NG Datentypen
Relax NG besitzt ebenfalls ein eingebautes Typ-System. Im Gegensatz zum W3C Schema wurde aber beim Design der Sprache entschieden,
das System minimal zu halten. Das eigene Typ-System umfaßt lediglich zwei Datentypen
(token und string) die sich auch nur in der Leerraumzeichenbehandlung voneinander unterscheiden.
Das bisher in den Relax NG Beispielen verwendete <text/>-Muster repräsentiert Null oder mehr Textknoten vom Datentyp
token. Werte vom Typ token werden entsprechend der XPath Funktion
normalize-space() normalisiert, indem alle Sequenzen
von Leerraumzeichen (Leerzeichen, Tab, Zeilenumbruch) durch ein Leerraumzeichen ersetzt und führende sowie abschließende Leerraumzeichen
entfernt werden. Der Datentyp string führt diese Normalisierung nicht durch und lässt den Zeichenkettenwert
unverändert.
1) <attribute name="available">
2) <choice>
3) <value>available</value>
4) <value type="token">checked out </value>
5) <value type="string">on hold </value>
6) </choice>
7) </attribute>
|
Die beiden Datentypen können beliebig in Mustern kombiniert werden. Im Code-Beispiel werden durch die <choice> (2)
und <value>-Pattern (3) drei feste Wert definiert, aus denen einer für das available-Attribut
gewählt werden kann. Wird kein Datentyp angegeben (3), so entspricht das dem Standardfall type="token". Das Leerzeichen hinter
out (4) würde durch einen Parser entfernt werden, die Leerzeichen von on hold (5) blieben hingegen erhalten.
Der string Typ sollte in einem Schema allerdings nur mit großer Vorsicht und auch nur wenn er unbedingt notwendig ist, eingesetzt werden.
Viele Nutzer und Anwendungen modifizieren durch Formatierungen, wie beispielsweise einrücken, Dokumente, um sie lesbarer zu machen.
Dies kann beim Einsatz des string-Typs allerdings
zu ungültigen XML-Instanzen führen, die aber nur sehr schwierig als solche zu erkennen sind. Aus diesem
Grund nutzt Relax NG den token-Datentyp als Standardwert.
Die Kombination aus <choice> und <value>-Mustern stellt im letzten Beispiel zudem
eine Aufzählung dar und ist somit das Relax NG
Equivalent zu dem xs:enumeration-Tag aus der W3C Schema Sprache. Mit Relax NG können aber auch sehr einfach "Ausschlußaufzählungen"
erzeugt werden, welche in einem W3C Schema so nicht möglich sind.
01) <attribute name="available">
02) <data type="token">
03) <except>
04) <value>available</value>
05) <value>checked out</value>
06) <value>on hold</value>
07) </except>
08) </data>
09) </attribute>
|
Hierfür muss das Beispiel lediglich um das <except>-Muster (3) ergänzt werden. Danach darf das
available-Attribut jeden Wert annehmen, außer available, checked out und
on hold.
Listen in Relax NG verhalten sich identisch zu einer Liste in einem W3C Schema und werden über das <list>-Muster (2) definiert.
Leider lässt sich die Anzahl der Listenelemente auch hier nur durch die vier Häufigkeitsmuster von Relax NG einschränken,
was somit auch im Bereich der Listen zu den bereits besprochenen Problemen führt.
01) <element name="isbn">
02) <list>
03) <zeroOrMore>
04) <value>1000000000</value>
05) <value>2643857021</value>
06) <value>9999999999</value>
07) </zeroOrMore>
08) </list>
09) </element>
10)
11) <isbn>2643857021 9999999999</isbn>
|
|
|
Einbinden externer Typ-Bibliotheken
Das nur zwei sehr allgemeine Datentypen in Relax NG vorhanden sind, kann mit zwei Gründe plausibel veranschaulicht werden. Erstens ist Relax NG mit dem Ziel
entworfen worden, die Dokumenten-Struktur zu validieren und weniger die Werte innerhalb dieser Struktur. Zweitens waren schon komplette Typ-Bibliotheken vorhanden,
so dass es den Entwicklern als nicht sinnvoll erschien, eine weitere Bibliothek für Relax NG zu konzipieren. Der Anwender hat statt dessen die Möglichkeit,
verschiedene externe Bibliotheken in seinem Relax NG Schema zu verwenden.
01) <element name="book"
02) datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
03) xmlns="http://relaxng.org/ns/structure/1.0">
04) <attribute name="available">
05) <value type="boolean">true</value>
06) </attribute>
07) <element name="titel">
08) <data type="token">
09) <param name="maxLength">255</param>
10) </data>
11) </element>
12) <element name="author-born">
13) <data type="date">
14) <param name="minInclusive">1900-01-01</param>
15) <param name="pattern">[0-9]{4}-[0-9]{2}-[0-9]{2}</param>
16) </data>
17) </element>
18) </element>
|
Das Einbinden einer externen Bibliothek erfolgt über das Attribut datatypeLibrary (2), welches im Beispiel die Datentypen
der W3C Schema Sprache referenziert. Nach der Angabe können alle Datentypen genauso innerhalb eines Relax NG Schemas verwendet werden, wie es bisher
für die eingebauten Typen token und string möglich war. datatypeLibrary ist dabei
ein Attribut, welches innerhalb eines Schemas vererbt wird. Das heißt, der Attributwert gilt auch für alle Kinder und zwar solange, bis er
wieder überschrieben wird.
Die Datentyp-Angabe erfolgt entweder in einem
<value>-Muster (5), wenn es sich um einen festen Wert handelt oder über das <data>-Pattern (8), wenn
der Wert des Elements variabel ist. Das <data>-Muster kann also an Stellen eingesetzt werden, wo eine Begrenzung des Wertebereiches notwendig ist,
die mit dem <text/>-Muster nicht erzielt werden kann.
Die Verwendung der vom W3C Schema bekannten Fassetten kann natürlich auch innerhalb eines Relax NG Schemas erfolgen, wo sie durch das
param-Muster repräsentiert werden. Das name-Attribut bestimmt die gewünschte Fassette.
Zeile 9 schränkt beispielsweise die mögliche Länge eines Titels auf 255 Zeichen ein, während die
minInclusive-Fassette (14) verhindert, dass Autoren vor dem 1.1.1900 geboren sein können.
Die in Zeile 15 verwendete pattern-Fassette für die Werteeinschränkung durch reguläre Ausdrücke
hat nichts mit dem Relax NG Konzept der Muster, die ja auch pattern genannt werden, zu tun und sollte nicht verwechselt
werden. Der Begriff entstammt der W3C Schema Spezifikation.
|
|
Bewertung
Die grundlegende Design-Entscheidung von Relax NG, dass das Validieren von
Struktur und Inhalt zwei unterschiedliche Probleme darstellt und somit auch durch zwei
verschiedene Werkzeuge (in enger Zusammenarbeit) gelöst werden sollte, eröffnet dem Anwender eine Vielzahl
neuer Möglichkeiten. Er ist nicht auf die eingebauten Typen beschränkt, sondern kann
eine beliebige, problemspezifische Typ-Bibliothek in seine Anwendung integrieren.
Relax NG nutzt für diesen Ansatz natürlich die sehr gute Vorarbeit der W3C Schema Sprache
im Bereich der Datentypen. Wäre eine entsprechende Bibliothek des W3C nicht schon vorhanden gewesen,
hätte sich der Relax NG Ansatz sicherlich nur schwierig durchsetzen lassen.
Neben der W3C Schema Typ-Bibliothek unterstützen die meisten Relax NG Implementationen auch noch DTD
kompatible Datentypen. Aber auch Prozessoren, die Mysql Datentypen wie timestamp
oder das Python Typ-System unterstützen, sind bereits vorhanden.
|
|
|