Ableitung durch Einschränkung

(Auszug aus "XML Schema" von Eric van der Vlist)

Einschränkung ist wahrscheinlich die meistverwendete und natürlichste Ableitungsmethode. Datentypen werden durch Einschränkung erzeugt, indem man neue Beschränkungen für die zulässigen Werte hinzufügt. W3C XML Schema verwendet selbst die Ableitung durch Einschränkung, um die meisten der abgeleiteten vordefinierten Datentypen zu definieren, wie etwa den Typ xs:positiveInteger, der eine Ableitung durch Einschränkung von xs:integer ist. Die Einschränkungen können entlang verschiedener Aspekte oder Achsen definiert werden, die W3C XML Schema »Facetten« nennt.

Eine Ableitung durch Einschränkung erreicht man, wenn man das Element xs:restriction verwendet und jede Facette definiert, indem man ein je eigenes Element dafür in das Element xs:restriction einbettet. Der Datentyp, auf den die Einschränkung angewendet wird, wird Basis-Datentyp genannt. Auf ihn kann man mit dem Attribut base verweisen, oder man kann ihn in dem Element xs:restriction definieren:

<xs:simpleType name="myInteger">
  <xs:restriction base="xs:integer">
    <xs:minInclusive value="-2"/>
    <xs:maxExclusive value="5"/>
  </xs:restriction>
</xs:simpleType>

Die Ableitung kann auch in zwei Schritten vorgenommen werden, indem man eine eingebettete Definition eines xs:simpleType verwendet:

<xs:simpleType name="myInteger">
  <xs:restriction>
    <xs:simpleType>
      <xs:restriction base="xs:integer">
        <xs:maxExclusive value="5"/>
      </xs:restriction>
    </xs:simpleType>
    <xs:minInclusive value="-2"/>
  </xs:restriction>
</xs:simpleType>

Die Elemente xs:minInclusive und xs:maxExclusive sind zwei Facetten, die auf einen ganzzahligen Datentyp angewendet werden können. Wie man aus ihren Namen erraten kann, geben sie den inklusiven Minimalwert (der angenommen werden kann) bzw. den exklusiven Maximalwert (der nicht mehr erlaubt ist) an. Wir werden im nächsten Abschnitt die Liste der Facetten einführen. Je nach Facette operiert diese entweder direkt auf dem Werteraum oder aber auf dem lexikalischen Raum des Datentyps, und dieselbe Facette kann unterschiedliche Effekte haben, je nachdem, auf welchen Datentyp sie angewendet wird.

Welche Facette auch immer auf einen Datentyp angewendet wird, die Semantik des zugrundeliegenden Typs bleibt unverändert. Die Liste der Facetten, die sich anwenden lassen, kann nicht erweitert werden, und man muß darauf achten, nach Möglichkeit einen Datentyp zu wählen, dessen zugrundeliegender Typ zum Zweck des Knotens paßt, in dem die Verwendung erfolgen soll. Auch wenn es beispielsweise möglich ist, einen String-Datentyp mit Hilfe von Mustern so einzuschränken, daß er auf Datumsangaben jenseits von ISO 8601 paßt, sollte diese Lösung nur verwendet werden, wenn sie unumgänglich ist. Dieser Datentyp würde nämlich immer noch als String betrachtet, und daher würden ihm Facetten wie beispielsweise xs:minInclusive oder xs:maxExclusive fehlen, die für Datums-Datentypen definiert sind, die für Strings jedoch keine Bedeutung (im Rahmen von W3C XML Schema) haben.

Die Auswirkungen der »richtigen« Auswahl des Basis-Datentyps, dessen Semantik so genau wie möglich zu der tatsächlichen Verwendung in den Instanzdokumenten paßt, wird noch kritischer werden, sobald Anwendungen mit Unterstützung für W3C XML Schema erhältlich sind. Solche Anwendungen werden unterschiedliches Verhalten zeigen, je nachdem, welche Information über den Datentyp im PSVI vorgefunden wird. Eine »falsche« Wahl wird zu Nebeneffekten führen. Beispielsweise schlagen die ersten Entwürfe für XPath 2.0 vor, Werte anhand vordefinierter Datentypen zu interpretieren, so daß die Ergebnisse von Tests auf Gleichheit oder die Sortierreihenfolge von den Datentypen abhinge.

Facetten

Bevor wir uns die Liste der Facetten ansehen, werden wir erörtern, wie sie funktionieren. Man kann sie in drei Kategorien klassifizieren: xs:whitespace legt die Whitespace-Verarbeitung fest, die zwischen dem geparsten und dem lexikalischen Raum stattfindet; diese Facette kann jedoch nur bei xs:string und xs:normalizedString verwendet werden. xs:pattern operiert auf dem lexikalischen Raum. Alle anderen Facetten schränken den Werteraum ein. Die Verfügbarkeit der Facetten und ihre Auswirkungen hängen von dem jeweiligen Datentyp ab, bei dem sie angewendet werden. Wir betrachten sie im Zusammenhang mit Gruppen von Datentypen, die denselben Satz Facetten unterstützen.

Strings mit zusammengefaßtem Whitespace

Diese Datentypen haben gemeinsam, daß es sich um Zeichen-Strings handelt (auch wenn W3C XML Schema rein technisch betrachtet nicht alle als Ableitungen von xs:string-Datentypen betrachtet) und daß Whitespace vor der Validierung zusammengefaßt wird, wie in der W3C-Empfehlung beschrieben: »Alle Vorkommen von #x9 (Tab), #xA (Linefeed) und #xD (Carriage Return) werden durch #x20 (Leerzeichen) ersetzt, daraufhin werden alle zusammenhängenden Folgen von #x20 zu einem einzelnen #x20 zusammengefaßt, und am Anfang oder am Ende stehende #x20 werden entfernt.«

Diese Datentypen sind: xs:ENTITY, xs:ID, xs:IDREF, xs:language, xs:Name, xs:NCName, xs:NMTOKEN, xs:token, Einschränkungen, xs:base64Binary, xs:hexBinary, xs:NOTATION und xs:QName. Ihre Facetten werden im nächsten Abschnitt erläutert.

xs:enumeration

xs:enumeration erlaubt es, eine Liste möglicher Werte anzugeben. Ein Beispiel hierfür:

<xs:simpleType name="schemaRecommendations">
  <xs:restriction base="xs:anyURI">
    <xs:enumeration value="http://www.w3.org/TR/xmlschema-0/"/>
    <xs:enumeration value="http://www.w3.org/TR/xmlschema-1/"/>
    <xs:enumeration value="http://www.w3.org/TR/xmlschema-2/"/>
  </xs:restriction>
</xs:simpleType>

Diese Facette schränkt den Werteraum ein. Für die meisten String-Datentypen (und die ihnen ähnlichen) sind lexikalischer und Werteraum identisch, so daß dies keinen Unterschied macht. Es besteht jedoch ein Unterschied bei Einschränkungen, xs:base64Binary und xs:QName. Zum Beispiel würden "http://dmoz.org/World/Français/" und "http://dmoz.org/World/Fran%c3%a7ais/" bei Einschränkungen als identisch betrachtet, die Zeilenumbrüche würden bei xs:base64Binary ignoriert, und beixs:QName würde die Prüfung mit den Tupeln {Namensraum-URI, lokaler Name} durchgeführt, wobei das im Schema und im Instanzdokument verwendete Präfix ignoriert würde.

Man sollte auch beachten, daß die Einschränkungen-Datentypen durch W3C XML Schema nicht »absolut gemacht« werden und xml:base nicht unterstützen. Das bedeutet, daß der im vorigen Beispiel definierte Typ »schemaRecommendations«, wenn er einem href-Attribut im Sinne von XLink zugewiesen wird, das folgende Instanzelement auf jeden Fall nicht validiert:

<a xml:base="http://www.w3.org/TR/" href="xmlschema-1/">
  XML Schema Teil 2: Datentypen
</a>

Wir können diesen Abschnitt nicht beenden, ohne über xs:NOTATION zu sprechen. Dieser Datentyp ist der einzige Fall eines vordefinierten Datentyps, der nicht unmittelbar in einem Schema verwendet werden kann. Er muß vielmehr mit Hilfe abgeleiteter Typen benutzt werden, die einen Satz von xs:enumeration-Facetten angeben. Auch wenn Notationen im richtigen Leben eher selten in Anwendungen zu finden sind, wäre dieses Buch nicht vollständig, ohne wenigstens ein Beispiel für Notationen zu geben. Nehmen wir das übliche Beispiel eines Bildes, das eine Notation in einem Attribut verwendet, um den Inhalt eines binären Feldes zu beschreiben:

<?xml version="1.0"?>
<picture type="png">
  iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAABmJLR0QA/wD/AP+gvaeTAAAA
  CXBIWXMAAAsSAAALEgHS3X78AAAAB3RJTUUH0QofESYx2JhwGwAAAFZJREFUeNqlj8ENwDAI
  A6HqGDCWp2QQ2AP2oI9IbaQm/dRPn9EJ7m7a56DPPDgiIoKIzGyBM9Pdx+4ueXabWVUBEJHR
  nLNJVbfuqspMAEOxwO9r/vX3BTEnKRXtqqslAAAAAElFTkSuQmCC
</picture>

Das Schema könnte wie folgt geschrieben werden; beachten Sie, wie die Notationen in dem Schema deklariert werden müssen, damit sie in einer xs:enumeration-Facette verwendet werden können:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:notation name="jpeg" public="image/jpeg"
        system="file:///usr/bin/xv"/>
    <xs:notation name="gif" public="image/gif"
        system="file:///usr/bin/xv"/>
    <xs:notation name="png" public="image/png"
        system="file:///usr/bin/xv"/>
    <xs:notation name="svg" public="image/svg"
        system="file:///usr/bin/xsmiles"/>
    <xs:notation name="pdf" public="application/pdf"
        system="file:///usr/bin/acroread"/>
    <xs:simpleType name="graphicalFormat">
        <xs:restriction base="xs:NOTATION">
            <xs:enumeration value="jpeg"/>
            <xs:enumeration value="gif"/>
            <xs:enumeration value="png"/>
            <xs:enumeration value="svg"/>
            <xs:enumeration value="pdf"/>
        </xs:restriction>
    </xs:simpleType>
    <xs:element name="picture">
        <xs:complexType>
            <xs:simpleContent>
                <xs:extension base="xs:base64Binary">
                    <xs:attribute name="type" type="graphicalFormat"/>
                </xs:extension>
            </xs:simpleContent>
        </xs:complexType>
    </xs:element>
</xs:schema>

xs:length

xs:length definiert eine feste Länge, die in Zeichen (im allgemeinen Fall) oder in Bytes (xs:hexBinary und xs:base64Binary) gemessen wird:

<xs:simpleType name="standardNotations">
  <xs:restriction base="xs:NOTATION">
    <xs:length value="8"/>
  </xs:restriction>
</xs:simpleType>

Diese Facette schränkt ebenfalls den Werteraum ein. Bei Einschränkungen kann es schwer sein, die Länge vorherzusagen, weil sie erst nach der Zeichennormalisierung bestimmt wird. Bei xs:QName ist es sogar noch schwieriger, da die Empfehlung zu W3C XML Schema die Länge eines xs:QName-Tupels nicht definiert hat. Glücklicherweise scheint es in der Praxis nicht sehr nützlich zu sein, die Länge dieser Datentypen einzuschränken. Es ist deswegen besser, die Längeneinschränkung für diese Datentypen zu vermeiden. Dieselbe Einschränkung gilt für die folgenden beiden Facetten.

xs:maxLength

xs:maxLength legt die maximale Länge fest, gemessen in Zeichen (allgemeiner Fall) oder in Bytes (xs:hexBinary und xs:base64Binary):

<xs:simpleType name="binaryImage">
  <xs:restriction base="xs:hexBinary">
    <xs:maxLength value="1024"/>
  </xs:restriction>
</xs:simpleType>

xs:minLength

xs:minLength definiert die Mindestlänge, gemessen in Zeichen (allgemeiner Fall) oder in Bytes (hexBinary und base64Binary):

<xs:simpleType name="longName">
  <xs:restriction base="xs:NCName">
    <xs:minLength value="6"/>
  </xs:restriction>
</xs:simpleType>

xs:pattern

xs:pattern legt ein Muster fest, das auf den String passen muß.

<xs:simpleType name="httpURI">
  <xs:restriction base="xs:anyURI">
    <xs:pattern value="http://.*"/>
  </xs:restriction>
</xs:simpleType>

Mehrere Muster-Facetten können in einem einzigen Ableitungsschritt angegeben werden. Sie werden anschließend durch ein logisches »Oder« zusammengefaßt (ein Wert paßt zu dem eingeschränkten Datentyp, wenn er zu einem der Muster paßt).

Da es unmöglich ist, eine einheitliche Reihenfolge festzulegen, die für alle regionalen Alphabete verwendbar wäre, hat W3C XML Schema beschlossen, die String-Datentypen als ungeordnet zu behandeln. Als Folge davon gibt es keine Facetten, die Mindest- oder Höchstwerte für String-Datentypen festlegen.

Andere Strings

Whitespace wird in diesen anderen Strings vor der Validierung nicht zusammengefaßt. Es steht eine weitere Facette (xs:whitespace) zusätzlich zu den eben beschriebenen zur Verfügung, mit der festgelegt wird, wie Whitespace bei den benutzerdefinierten Datentypen behandelt werden soll, die von diesen Typen abgeleitet werden.

Diese Datentypen sind: xs:normalizedString und xs:string.

xs:whitespace

xs:whitespace legt fest, wie Whitespace – d.h. #x20 (Leerzeichen), #x9 (Tab), #xA (Linefeed) und #xD (Carriage Return) – bei diesem Datentyp behandelt werden soll:

<xs:simpleType name="CapitalizedNameWS">
  <xs:restriction base="xs:string">
    <xs:whiteSpace value="collapse"/>
    <xs:pattern value="([A-Z]([a-z]*) ?)+"/>
  </xs:restriction>
</xs:simpleType>

Die möglichen Werte für die xs:whitespace-Facette sind »preserve« (Whitespace wird unverändert beibehalten), »replace« (alle Vorkommen eines der Whitespace-Zeichen werden durch ein Leerzeichen ersetzt) und »collapse« (am Anfang und am Ende stehender Whitespace wird entfernt, alle anderen zusammenhängenden Folgen von Whitespace werden durch ein einzelnes Leerzeichen ersetzt). Diese Facette ist insofern untypisch, weil sie festlegt, wie ein Wert bearbeitet werden soll, bevor irgendwelche Validierungstests für den Wert durchgeführt werden. In obigem Beispiel ermöglicht es die Whitespace-Einstellung »collapse«, in dem Muster auf ein einfaches Leerzeichen (»?«) zu testen. Dadurch werden die Whitespace-Zeichen zusammengefaßt, bevor das Muster getestet wird, so daß letztlich beliebig viele Leerzeichen durch das Muster abgedeckt werden.

Das Whitespace-Verhalten kann durch eine Einschränkung nicht gelockert werden: Wenn für einen Datentyp Whitespace auf »preserve« gesetzt ist, können die von ihm abgeleiteten Datentypen beliebiges Whitespace-Verhalten haben. Wenn sein Whitespace auf »replace« gesetzt ist, können die abgeleiteten Datentypen nur die Whitespace-Einstellungen »replace« oder »collapse« tragen. Ist sein Whitespace »collapse«, müssen alle von ihm abgeleiteten Datentypen dasselbe Verhalten zeigen. Das bedeutet, daß xs:string der einzige Datentyp ist, der für die Ableitung von Datentypen ohne jegliche Whitespace-Verarbeitung verwendet werden kann, während xs:string und xs:normalizedString die einzigen Datentypen sind, die zur Ableitung von Datentypen geeignet sind, die Whitespace-Zeichen normalisieren.

In der Praxis ist diese Facette für benutzerdefinierte Datentypen nicht wirklich gut einsetzbar, da die Whitespace-Verarbeitung weitgehend die Auswahl des zu verwendenden vordefinierten Datentyps vorgibt. Wenn wir einen Datentyp benötigen, der keine Whitespace-Verarbeitung vornimmt, müssen wir xs:string nehmen, nicht jedoch xs:whitespace . Wenn wir einen Datentyp brauchen, der Whitespace normalisiert, können wir direkt xs:normalizedString verwenden, statt xs:string zu benutzen und dann die xs:whitespace-Facette anzuwenden, weil dies denselben Effekt hat. Wenn wir einen Datentyp brauchen, der Whitespace zusammenfaßt, können wir xs:token benutzen, wenn es sich um einen String handelt – da, wie gesagt, xs:token kein Token in der üblichen Verwendung des Wortes, sondern vielmehr ein »tokenisierter String« ist –, sowie jeden anderen Nicht-String-Datentyp. Die Whitespace-Verarbeitung ist dann bereits auf »collapse« gesetzt, auch ohne daß xs:whitespace verwendet werden müßte. Das vorige Beispiel ist demnach gleichbedeutend mit:

<xs:simpleType name="CapitalizedNameWS">
  <xs:restriction base="xs:token">
    <xs:pattern value="([A-Z]([a-z]*) ?)+"/>
  </xs:restriction>
</xs:simpleType>

Technisch gesprochen, hat die W3C-Arbeitsgruppe die Facette xs:whitespace für xs:token und die davon abgeleiteten Datentypen nicht »fixiert«. Allerdings ist der Wert von xs:whitespace für xs:token auf »collapse« gesetzt worden. Da die Facette bei weiteren Ableitungen nicht gelockert werden kann, kann dieser Wert bei keinem Datentyp geändert werden, der von diesen Datentypen abgeleitet ist.

Gleitkomma-Datentypen

Die Facetten von xs:double und xs:float werden in den nächsten Abschnitten beschrieben.

xs:enumeration

xs:enumeration ermöglicht es, eine Liste möglicher Werte anzugeben. Diese Facette operiert auf dem Werteraum. Beispiel:

<xs:simpleType name="enumeration">
  <xs:restriction base="xs:float">
    <xs:enumeration value="-INF"/>
    <xs:enumeration value="1.570796327"/>
    <xs:enumeration value="3e3"/>
  </xs:restriction>
</xs:simpleType>

Dieser einfache Typ paßt auf Konstanten wie:

 

<enumeration>
  1.570796327
</enumeration>

<enumeration>
  3e3
</enumeration>

<enumeration>
  003000.0000
</enumeration>

Das Beispiel zeigt (wie wir bereits kurz bei Einschränkungenxs:QName und xs:base64Binary gesehen haben) zwei unterschiedliche lexikalische Darstellungen (»3e3« und »003000.0000«) für denselben Wert. Es zeigt auch, daß beide lexikalischen Darstellungen denselben Wert haben, so daß beide durch einen der Aufzählungswerte akzeptiert werden.

xs:maxExclusive

xs:maxExclusive legt einen Maximalwert fest, der nicht erreicht werden darf:

<xs:simpleType name="maxExclusive">
  <xs:restriction base="xs:float">
    <xs:maxExclusive value="10"/>
  </xs:restriction>
</xs:simpleType>

Dieser Datentyp validiert »9.999999999999999«, nicht jedoch »10«.

Die Facette xs:maxExclusive ist besonders nützlich für Datentypen wie xs:float , xs:double, xs:decimal und sogar für Datums-/Zeitwerte, die mit infinitesimalen Werten umgehen können und bei denen es nicht möglich ist, den größten Wert zu bestimmen, der kleiner als ein gegebener Wert ist.

xs:maxInclusive

xs:maxInclusive legt einen Maximalwert fest, der erreicht werden darf:

<xs:simpleType name="thousands">
  <xs:restriction base="xs:double">
    <xs:maxInclusive value="1e3"/>
  </xs:restriction>
</xs:simpleType>

xs:minExclusive

xs:minExclusive legt einen Minimalwert fest, der nicht erreicht werden darf:

<xs:simpleType name="strictlyPositive">
  <xs:restriction base="xs:double">
    <xs:minExclusive value="0"/>
  </xs:restriction>
</xs:simpleType>

xs:minInclusive

xs:minInclusive legt einen Minimalwert fest, der erreicht werden darf:

<xs:simpleType name="positive">
  <xs:restriction base="xs:double">
    <xs:minInclusive value="0"/>
  </xs:restriction>
</xs:simpleType>

xs:pattern

xs:pattern legt ein Muster fest, das auf den lexikalischen Wert des Datentyps passen muß:

<xs:simpleType name="nonScientific">
    <xs:restriction base="xs:float">
        <xs:pattern value="[^eE]*"/>
    </xs:restriction>
</xs:simpleType>
<xs:simpleType name="noLeading0">
    <xs:restriction base="xs:float">
        <xs:pattern value="[^0].*"/>
    </xs:restriction>
</xs:simpleType>

Dieses Beispiel zeigt, wie ein Muster, das auf dem lexikalischen Wert der Gleitkommazahl operiert, die Verwendung wissenschaftlicher Notation (xxxEyyy) oder führender Nullen verbieten kann.

xs:pattern ist die einzige Facette, die direkt auf dem lexikalischen Raum des Datentyps operiert.

Datums- und Zeit-Datentypen

Diese Datentypen sind teilgeordnet, daher können Schranken definiert werden, auch wenn es einige Einschränkungen dafür gibt. Diese Datentypen sind: xs:date, xs:dateTime, xs:duration, xs:gDay, xs:gMonth, xs:gMonthDay, xs:gYear, xs:gYearMonth und xs:time. Ihre Facetten sind dieselben wie die der Gleitkomma-Datentypen, wie in den nächsten Abschnitten gezeigt wird:

xs:enumeration

xs:enumeration ermöglicht es, eine Liste möglicher Werte anzugeben. Diese Facette operiert auf dem Werteraum. Beispiel:

<xs:simpleType name="ModernSwissHistoricalDates">
    <xs:restriction base="xs:gYear">
        <xs:enumeration value="1864"/>
        <xs:enumeration value="1872"/>
        <xs:enumeration value="1914"/>
        <xs:enumeration value="1939"/>
        <xs:enumeration value="1971"/>
        <xs:enumeration value="1979"/>
        <xs:enumeration value="1992"/>
    </xs:restriction>
</xs:simpleType>

Dieser einfache Typ paßt auf Konstanten wie:

1939

Da keine Zeitzone für die Datumsangaben in der Aufzählung angegeben ist, ist die Zeitzone unbestimmt. Diese Datumsangaben passen auf kein Datum, dessen Zeitzone angegeben ist:

1939Z

oder:

1939+10:00

Das gleiche Problem tritt auf, wenn Aufzählungen eine Zeitzone enthalten, wie etwa in:

<xs:simpleType name="wakeUpTime">
  <xs:restriction base="xs:time">
    <xs:enumeration value="07:00:00-07:00"/>
    <xs:enumeration value="07:15:00-07:00"/>
    <xs:enumeration value="07:30:00-07:00"/>
    <xs:enumeration value="07:45:00-07:00"/>
    <xs:enumeration value="08:00:00-07:00"/>
  </xs:restriction>
</xs:simpleType>

Dieser neue Datentyp paßt auf:

07:00:00-07:00

wie auch:

11:00:00-04:00

und sogar:

07:15:00-07:15

Die Aufzählung validiert jedoch keine Zeitangabe ohne Zeitzone.

Auch wenn es problematisch und fragwürdig sein mag, sowohl Zeitangaben mit als auch solche ohne Zeitzone zu verarbeiten, ist es möglich, Aufzählungen von Werten mit und ohne Zeitzonen zu mischen:

<xs:simpleType name="sevenOClockPST">
    <xs:restriction base="xs:time">
        <xs:enumeration value="07:00:00-07:00"/>
        <xs:enumeration value="07:00:00"/>
    </xs:restriction>
</xs:simpleType>

xs:maxExclusive

xs:maxExclusive legt einen Maximalwert fest, der nicht erreicht werden darf:

<xs:simpleType name="beforeY2K">
    <xs:restriction base="xs:dateTime">
        <xs:maxExclusive value="2000-01-01T00:00:00Z"/>
    </xs:restriction>
</xs:simpleType>

Dieser Datentyp validiert jede Zeitangabe, die zeitlich vor Y2K UTC liegt, wie beispielsweise:

1999-12-31T23:59:59Z

oder:

1999-12-31T23:59:59.999999999999Z

Er validiert auch die folgende Angabe, selbst wenn sie in einer beliebigen anderen Zeitzone ausgedrückt wird, wie beispielsweise:

2000-01-01T11:59:59+12:00

Er validiert hingegen nicht:

2000-01-01T00:00:00Z

Das Unbestimmheitsintervall von +/-14 Stunden wird angewendet, wenn mit einer Datums-/Zeitangaben ohne Zeitzone verglichen werden soll. Die größte zulässige Datums-/Zeitangabe ohne Zeitzone (ohne Bruchteile von Sekunden mit einzubeziehen) wäre in unserem Beispiel also:

1999-12-31T09:59:59

xs:maxInclusive

xs:maxInclusive legt einen Maximalwert fest, der erreicht werden darf:

<xs:simpleType name="AQuarterOrLess">
  <xs:restriction base="xs:duration">
    <xs:maxInclusive value="P3M"/>
  </xs:restriction>
</xs:simpleType>

Dieser Datentyp validiert alle Zeitdauern, die drei Monaten oder weniger entsprechen. Zeitdauern wie P2M (zwei Monate) oder P3M (drei Monate) sind zulässig. Wenn Monate und Tage gleichzeitig angegeben werden, ist P2M30D (zwei Monate und 30 Tage) gültig, hingegen werden P2M31D (zwei Monate und 31 Tage) oder auch P2M30DT1S (zwei Monate, 30 Tage und eine Sekunde) zurückgewiesen wegen der Unbestimmtheit der tatsächlichen Dauer, wenn Teile von Jahr und Monat auf der einen Seite, Tag/Stunde/Minute/Sekunde auf der anderen Seite verwendet werden.

xs:minExclusive

xs:minExclusive legt einen Minimalwert fest, der nicht erreicht werden darf:

<xs:simpleType name="afterTeaTimeInParisInSummer">
  <xs:restriction base="xs:time">
    <xs:minExclusive value="17:00:00+02:00"/>
  </xs:restriction>
</xs:simpleType>

xs:minInclusive

xs:minInclusive legt einen Minimalwert fest, der erreicht werden darf:

<xs:simpleType name="afterOrOnThe20th">
  <xs:restriction base="xs:gDay">
    <xs:minInclusive value="---20"/>
  </xs:restriction>
</xs:simpleType>

Wir können auch unser Beispiel mit der Zeitdauer noch einmal aufnehmen und festlegen:

<xs:simpleType name="AQuarterOrMore">
  <xs:restriction base="xs:duration">
    <xs:minInclusive value="P3M"/>
  </xs:restriction>
</xs:simpleType>

Dieser Datentyp validiert alle Zeitdauern, die drei Monate oder länger dauern. Zeitdauern wie etwa P4M (vier Monate) oder P3M (drei Monate) bestehen den Test. Wenn sowohl Monate als auch Tage verwendet werden, ist P2M31D (zwei Monate und 31 Tage) gültig, P2M30D (zwei Monate und 30 Tage) oder gar P2M30DT23H59M59S (zwei Monate, 30 Tage, 23 Stunden, 59 Minuten und 59 Sekunden) werden jedoch wegen der Unbestimmtheit der tatsächlichen Zeitdauer zurückgewiesen.

Aufgrund dieser Unbestimmtheit betrachtet W3C XML Schema unseren dritten Monat als 30tägig, wenn wir xs:minInclusive anwenden, jedoch als 31tägig, wenn wir xs:maxInclusive anwenden. In der Praxis kann es sich als klug erweisen, die Verwendung von Kombinationen, die eine solche Unbestimmtheit zulassen, für ungültig zu erklären. Wir werden im nächsten Kapitel sehen, wie man das mit einem Muster erreicht.

xs:pattern

xs:pattern legt ein Muster fest, das auf den lexikalischen Wert des Datentyps passen muß. Wir werden Muster im nächsten Kapitel in allen Einzelheiten beschreiben. Um eine Vorstellung davon zu gewinnen, wie Muster aussehen, betrachten Sie den folgenden Datentyp. Er verbietet die Verwendung einer Zeitzone bei einem Datentyp von xs:dateTime:

<xs:simpleType name="noTimeZone">
  <xs:restriction base="xs:dateTime">
    <xs:pattern value=".*T[^Z+-]*"/>
  </xs:restriction>
</xs:simpleType>

Der Datentyp Integer und seine Ableitungen

Dies sind die folgenden Datentypen: Beschreibung, xs:int, xs:integer, xs:long, xs:negativeInteger, xs:nonNegativeInteger, xs:nonPositiveInteger, xs:positiveInteger, xs:short, xs:unsignedByte, xs:unsignedInt, xs:unsignedLong und xs:unsignedShort.

Sie akzeptieren die gleichen Facetten wie die Gleitkomma-, die Datums- und Zeit-Datentypen, die wir eben betrachtet haben, sowie eine zusätzliche Facette, um die Anzahl von Ziffern einzuschränken.

xs:totalDigits

xs:totalDigits legt die Maximalzahl von Dezimalziffern fest:

<xs:simpleType name="totalDigits">
  <xs:restriction base="xs:integer">
    <xs:totalDigits value="5"/>
  </xs:restriction>
</xs:simpleType>

Dieser Datentyp nimmt nur ganze Zahlen mit höchstens fünf Dezimalziffern auf.

xs:totalDigits operiert auf dem Werteraum. Daher paßt beispielsweise die Zahl »000012345«, deren kanonischer Wert »12345« ist, zu dem soeben definierten Datentyp.

Dezimalzahlen

Der einfache Datentyp xs:decimal akzeptiert alle Facetten der Integer-Datentypen und zusätzlich eine Facette, mit der sich die Anzahl der Nachkommastellen festlegen läßt.

xs:fractionDigits

xs:fractionDigits gibt die maximal erlaubte Anzahl von Dezimalziffern im gebrochenen Teil (nach dem Dezimalpunkt) an:

<xs:simpleType name="fractionDigits">
  <xs:restriction base="xs:decimal">
    <xs:fractionDigits value="2"/>
  </xs:restriction>
</xs:simpleType>

Dieser Datentyp nimmt nur Dezimalbrüche mit höchstens zwei Nachkommastellen auf.

xs:fractionDigits operiert auf dem Werteraum. Daher paßt beispielsweise der Dezimalbruch »1.12000«, dessen kanonischer Wert »1.12« ist, zu dem soeben definierten Datentyp.

Boolescher Datentyp

Mit nur einer einzigen zulässigen Facette ist xs:boolean der einfachste Datentyp, was die Einschränkungsfacetten angeht. Der Werteraum dieses einfachen Datentyps ist auf »true« und »false« beschränkt, im lexikalischen Raum befinden sich jedoch auch »0« und »1«. Die Facette xs:pattern kann dazu verwendet werden, eines dieser Formate auszuschließen.

xs:pattern

Die Funktionalität von xs:pattern ist normalerweise sehr reichhaltig. Angesichts der wenigen möglichen Werte für xs:boolean scheint die einzige Verwendung hier jedoch darin zu bestehen, eines der Formate festzuschreiben:

<xs:simpleType name="trueOrFalse">
  <xs:restriction base="xs:boolean">
    <xs:pattern value="true"/>
    <xs:pattern value="false"/>
  </xs:restriction>
</xs:simpleType>

Listen-Datentypen

Die verfügbaren Facetten für die Listen-Datentypen (xs:IDREFS, xs:ENTITIES und xs:NMTOKENS) sind diejenigen, die auch für die durch Auflistung abgeleiteten Datentypen verfügbar sind, wie wir im nächsten Abschnitt sehen werden.

Mehrfache Einschränkungen und fixe Attribute

Neue Einschränkungen können auf Datentypen angewendet werden, die bereits durch Einschränkung von anderen Typen abgeleitet worden sind.

Wenn die neuen Einschränkungen Facetten betreffen, die vorher noch nicht eingeschränkt worden waren, werden die neuen Facetten einfach der Menge der bereits festgelegten Facetten hinzugefügt. Der Werteraum und der lexikalische Raum des neuen Datentyps sind jeweils die Schnittmenge aller Einschränkungen. Es wird komplizierter, wenn dieselben Facetten umdefiniert werden; dann können Einschränkungsfacetten den Werteraum erweitern.

Was Mehrfachdefinitionen angeht, können wir die Facetten in vier Kategorien einteilen, die in den nächsten Abschnitten beschrieben werden.

Facetten, die geändert werden können, dabei aber restriktiver werden müssen

Dies ist der am weitesten verbreitete Fall. xs:enumeration, xs:fractionDigits, xs:maxExclusive, Beschreibung, xs:maxLength, xs:minExclusive, xs:minInclusive, xs:minLength und xs:totalDigits gehören hierzu.

Bei all diesen Facetten ist es verboten, eine Facette hinzuzufügen, die den Werteraum des Basis-Datentyps erweitert. Die folgenden Beispiele illustrieren derartige Fehler:

<xs:simpleType name="minInclusive">
  <xs:restriction base="xs:float">
     <xs:minInclusive value="10"/>
  </xs:restriction>
</xs:simpleType>
<xs:simpleType name="minInclusive2">
  <xs:restriction base="minInclusive">
    <xs:minInclusive value="0"/>
  </xs:restriction>
</xs:simpleType>


oder:

<xs:simpleType name="enumeration">
  <xs:restriction base="xs:float">
      <xs:enumeration value="-INF"/>
      <xs:enumeration value="1.618033989"/>
      <xs:enumeration value="3e3"/>
  </xs:restriction>
</xs:simpleType>
<xs:simpleType name="enumeration2">
  <xs:restriction base="enumeration">
      <xs:enumeration value="0"/>
  </xs:restriction>
</xs:simpleType>

Facetten, die nicht geändert werden können

Die Facettexs:length ist die einzige in dieser Kategorie. Die Länge eines abgeleiteten Datentyps kann nicht neu definiert werden, wenn die Länge seines Elterntyps bereits festgelegt war.

xs:length kann als Abkürzung dafür angesehen werden, den Facetten xs:maxLength und xs:minLength den gleichen Wert zuzuweisen. Das Verhalten paßt genau zu dem, was passiert, wenn diese beiden Facetten mit demselben Wert verwendet werden: Neue Werte für xs:maxLength müssen kleiner oder gleich der Länge sein, neue Werte für xs:minLength müssen größer oder gleich der Länge sein. Da xs:minLength außerdem kleiner oder gleich xs:maxLength sein muß, besteht die einzige Möglichkeit darin, daß alle genau denselben Wert behalten müssen, der bereits vorher für die Länge definiert worden war.

Facetten, die die Schnittmenge der lexikalischen Räume bilden

Die Facette xs:pattern ist die einzige, die mehrfach hintereinander angewendet werden kann. Sie schränkt stets den lexikalischen Raum ein, indem sie eine direkte Schnittmenge der lexikalischen Räume bildet. Der folgende Datentyp nonScientificNoLeading0 wird versuchen, sowohl das Muster für den Basis-Datentyp als auch für die neue Einschränkung zu erfüllen:

<xs:simpleType name="nonScientific">
  <xs:restriction base="xs:float">
    <xs:pattern value="[^eE]*"/>
  </xs:restriction>
</xs:simpleType>
<xs:simpleType name="nonScientificNoLeading0">
  <xs:restriction base="nonScientific">
    <xs:pattern value="[^0].*"/>
  </xs:restriction>
</xs:simpleType>

Facetten, die ihre Arbeit vor dem lexikalischen Raum erledigen

xs:whitespace ist eine bemerkenswerte Ausnahme. Diese Facette legt die Whitespace-Verarbeitung fest und kann tatsächlich die Menge der akzeptierten Instanzdokumente im Zuge einer »Einschränkung« erweitern, wie das folgende Beispiel zeigt:

<xs:simpleType name="greetings">
  <xs:restriction base="xs:string">
     <xs:whiteSpace value="replace"/>
       <xs:enumeration value="hi"/>
       <xs:enumeration value="hallo"/>
       <xs:enumeration value="wie geht’s?"/>
     </xs:restriction>
   </xs:simpleType>
<xs:simpleType name="restricted-greetings">
   <xs:restriction base="greetings">
      <xs:whiteSpace value="collapse"/>
   </xs:restriction>
</xs:simpleType>

Der erste der beiden Datentypen (»greetings«) akzeptiert den String

wie geht’s?

Er weist den folgenden jedoch zurück:

wie    geht’s?

Der Typ, der aus der »Einschränkung« hervorgeht, akzeptiert beide Strings.

Fixe Facetten

Jede Facette (außer xs:enumeration und xs:pattern) erlaubt ein Attribut namens fixed. Wenn dieses den Wert true hat, wird es damit unmöglich, diese Facette während späterer Ableitungen durch Einschränkung noch zu verändern.

Wenn wir sicherstellen wollen, daß der mittels minInclusive angegebene Minimalwert nicht mehr verändert werden kann, schreiben wir:

<xs:simpleType name="minInclusive">
  <xs:restriction base="xs:float">
    <xs:minInclusive value="10" fixed="true"/>
  </xs:restriction>
</xs:simpleType>

Dies ist die Methode, die das Schema für W3C XML Schema benutzt, um die Werte von Facetten festzulegen, die zur Ableitung der vordefinierten Datentypen verwendet werden. Beispielsweise wird der Typ xs:integer von xs:decimal wie folgt abgeleitet:

<xs:simpleType name="integer" id="integer">
  <xs:restriction base="xs:decimal">
    <xs:fractionDigits value="0" fixed="true"/>
  </xs:restriction>
</xs:simpleType>


<xs:enumeration> und <xs:pattern> können nicht fixiert werden.

   

zum Seitenanfang

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema XML Schema bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © 2003 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XML Schema" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O’Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de