Bei diesem Dokument handelt es sich um eine Übersetzung eines W3C-Textes. Dieser Text ist urheberrechtlich geschützt; bitte beachten Sie die nachfolgenden Hinweise des Originaldokuments. Die Rechte an der Übersetzung liegen bei den Übersetzern sowie beim Verlag Addison-Wesley. Die Übersetzung hat keine durch das W3C legitimierte, normative Wirkung. Das einzige maßgebliche Dokument ist das englische Original.
Bitte senden Sie Fehler und Korrekturen zur deutschen Fassung an die Übersetzer.
Kommentare der Übersetzer, die als solche gekennzeichnet sind, unterliegen dem Urheberrecht der Übersetzer. Sie sind nicht Bestandteil des Ursprungsdokuments.
Copyright ©2001 W3C® (MIT, INRIA, Keio), Alle Rechte vorbehalten. Es gelten die W3C-Regeln zu Haftung, Warenzeichen und Verwendung des Dokuments sowie die Lizenzregeln für Software.
“XML Schema Teil 0: Einführung” ist ein nicht-normatives Dokument mit dem Ziel, eine gut lesbare Beschreibung der Möglichkeiten von XML Schema zu bieten und schnell zur Erstellung von Schemata mit der XML Schema Sprache hinzuführen. XML Schema Teil 1: Struktur und XML Schema Teil 2: Datentypen bilden die vollständige normative Beschreibung der XML-Schema-Sprache. Diese Einführung beschreibt die Sprachkonstrukte anhand zahlreicher Beispiele, ergänzt durch etliche Verweise auf die normativen Texte.
Dieser Abschnitt beschreibt den Status dieses Dokuments zum Zeitpunkt seines Erscheinens. Andere Dokumente können dieses ersetzen. Der letzte Stand der Dokumentreihe wird vom W3C gepflegt.
Dieses Dokument wurde von Mitgliedern des W3C und anderen Interessierten überprüft und vom Direktor als W3C-Empfehlung bestätigt. Es handelt sich um ein stabiles Dokument, welches als Referenz eingesetzt werden kann. Die Rolle des W3C bei der Erstellung der Empfehlungen liegt darin, die Aufmerksamkeit auf die Spezifikation zu ziehen und ihren weitverbreiteten Einsatz anzuregen. Dies erweitert die Funktionalität und die Interoperabilität des Web.
Dieses Dokument wurde von der W3C XML Schema Arbeitsgruppe im Rahmen der XML Activity des W3C erstellt. Die Ziele der XML-Schema-Sprache werden im Dokument XML Schema-Anforderungen erläutert. Die Autoren dieses Dokuments sind die Mitglieder der XML Schema Arbeitsgruppe. Andere Teile des Dokuments haben andere Herausgeber.
In diese Version des Dokuments wurden einige redaktionelle Änderungen aus früheren Versionen eingearbeitet.
Bitte melden Sie Fehler in diesem Dokument an www-xml-schema-comments@w3.org(Archiv).
Die Liste der bekannten Fehler in dieser Spezifikation ist unter http://www.w3.org/2001/05/xmlschema-errata verfügbar.
Nur die englische Version dieses Dokuments ist normativ. Informationen zu Übersetzungen dieses Dokuments sind unter http://www.w3.org/2001/05/xmlschema-translations verfügbar.
Eine Aufstellung aktueller W3C-Empfehlungen und anderer technischer Dokumente ist unter http://www.w3.org/TR/ zu finden.
1 Einleitung
2 Grundlegende Konzepte: Die Buchbestellung
2.1 Das Schema für Buchbestellungen
2.2 Definition von komplexen Typen, Elementen und Attributen
2.2.1 Häufigkeitsbeschränkungen
2.2.2 Globale Elemente und Attribute
2.2.3 Namenskonflikte
2.3 Einfache Typen
2.3.1 Listentypen
2.3.2 Vereinigungstypen
2.4 Definition von anonymen Typen
2.5 Inhalt von Elementen
2.5.1 Ableitung komplexer Typen aus einfachen Typen
2.5.2 Gemischter Inhalt
2.5.3 Leeres Inhaltsmodell
2.5.4 anyType
2.6 Anmerkungen
2.7 Aufbau von Inhaltsmodellen
2.8 Attributgruppen
2.9 Nil-Werte
3 Weiterführende Konzepte I: Namensräume, Schemata und Qualifizierung
3.1 Ziel-Namensräume und nicht qualifizierte lokale Elemente und Attribute
3.2 Qualifizierte lokale Elemente und Attribute
3.3 Globale und lokale Deklarationen
3.4 Nicht deklarierte Ziel-Namensräume
4 Weiterführende Konzepte II: Die internationale Buchbestellung
4.1 Ein Schema in mehreren Dokumenten
4.2 Typ-Ableitung durch Erweiterung
4.3 Benutzung abgeleiteter Typen in Instanzdokumenten
4.4 Ableitung komplexer Typen durch Einschränkung
4.5 Umdefinieren von Typen und Gruppen
4.6 Ersetzungsgruppen
4.7 Abstrakte Elemente und Typen
4.8 Kontrolle über die Erzeugung und Verwendung von abgeleiteten Typen
5 Weiterführende Konzepte III: Die Kundenaufstellung
5.1 Spezifikation von Eindeutigkeit
5.2 Deklaration von Schlüsseln und Schlüsselreferenzen
5.3 XML Schema Beschränkungen versus XML 1.0 ID-Attribute
5.4 Import von Typen
5.4.1 Typ-Bibliotheken
5.5 Any-Element, Any-Attribut
5.6 schemaLocation
5.7 Konformität
A Danksagungen
B Einfache Typen und ihre Fassetten
C Verwendung von Entities
D Reguläre Ausdrücke
E Index
Dieses Dokument, “XML Schema Teil 0: Einführung”, bietet eine leicht zugängliche Beschreibung der XML Schema Definitionssprache und sollte zusammen mit der formalen Beschreibung der Sprache in Teil 1 und Teil 2 der XML Schema Spezifikation verwendet werden. Die Zielgruppe für dieses Dokument sind unter anderem Anwendungsentwickler, deren Programme Schema-Dokumente lesen und schreiben sollen, und Schema-Autoren, welche die Sprachkonstrukte kennen lernen müssen, insbesondere diejenigen Sprachkonstrukte, die über die Funktionalität von DTDs hinausgehen. Der Text setzt ein grundlegendes Verständnis von XML 1.0 und XML-Namespaces voraus. Jedes Kapitel der Einführung stellt neue Sprachkonstrukte vor und beschreibt diese im Zusammenhang mit anschaulichen Beispielen.
Kapitel 2 deckt die Grundlagen von XML Schema ab. Es erklärt, wie Elemente und Attribute definiert werden, die in XML-Dokumenten auftreten. Es erläutert den Unterschied zwischen einfachen Typen (Simple Types) und komplexen Typen (Complex Types), die Definition komplexer Typen und den Einsatz von einfachen Typen in Element- und Attributwerten, Schema-Annotationen, einen einfachen Mechanismus für die Wiederverwendung von Element- und Attribut-Definitionen und Nil-Werte.
Kapitel 3, das erste Kapitel mit weiterführenden Konzepten, erklärt die Grundlagen der Benutzung von Namensräumen in XML- und Schema-Dokumenten. Dieses Kapitel ist für das Verständnis vieler Themen in den anderen weiterführenden Kapiteln wichtig.
Kapitel 4, das zweite Kapitel mit weiterführenden Konzepten, beschreibt Mechanismen zur Ableitung neuer Typen von bestehenden und erklärt, wie man diese Ableitung kontrolliert. Das Kapitel zeigt außerdem einen Weg, um Fragmente eines Schemas aus mehreren Quellen zusammenzuführen, sowie die Substituierung von Elementen.
Kapitel 5 deckt weitere höhere Sprachkonstrukte ab, unter anderem einen Mechanismus, um Eindeutigkeit von Elementen und Attributen zu spezifizieren, einen Weg, um Typen über Namensräume hinweg zu verwenden sowie einen Mechanismus, um Typen auf Basis von Namensräumen zu erweitern. Außerdem beschreibt Kapitel 5, wie Dokumente auf Konformität geprüft werden.
Zusätzlich zu den eben beschriebenen Kapiteln enthält die Einführung eine Reihe von Anhängen, die detaillierte Referenzinformationen über einfache Typen und eine Sprache für reguläre Ausdrücke enthalten.
Die Einführung ist ein nicht-normatives Dokument, d.h. es bietet aus Sicht des W3C keine definierende Spezifikation der XML-Schema-Sprache. Die Beispiele und anderes erklärendes Material in diesem Dokument werden angeboten, um Ihnen beim Verständnis von XML Schema zu helfen, aber sie bieten nicht immer endgültige Antworten. In diesem Fall müssen Sie die XML Schema Spezifikation konsultieren. Um Ihnen dabei zu helfen, bieten wir etliche Links, die auf die relevanten Teile der Spezifikation verweisen. Genauer gesagt sind XML Schema-Begriffe, die im Text der Einführung erwähnt werden, mit einem Index von Elementnamen und Attributen verlinkt, sowie mit einer zusammenfassenden Tabelle, beide in dieser Einführung. Diese Tabelle und der Index enthalten Verweise auf die relevanten Kapitel von XML Schema Teil 1 und 2.
Der Zweck eines Schemas ist es, eine Klasse von XML-Dokumenten zu definieren. Deshalb wird häufig der Begriff “Instanzdokument” oder kurz “Instanz” verwendet, um ein Dokument zu beschreiben, das einem bestimmten Schema entspricht. In der Tat müssen weder Instanzen noch Schemata als Dokument per se existieren. Sie können genauso gut Datenströme aus Bytes sein, Felder in einem Datenbanksatz oder eine Sammlung von XML-Infoset Informationseinheiten. Um die Einführung einfach zu halten, haben wir uns entschieden, von Instanzen oder Schemata immer so zu sprechen, als seien sie Dokumente.
Beginnen wir mit einem Instanzdokument in einer Datei namens “best.xml”. Es beschreibt eine Buchbestellung, wie sie vom Bestellungs- und Rechnungswesen einer Online-Buchhandlung erstellt werden könnte:
<?xml version="1.0"?> <Bestellung bestelldatum="2000-05-10"> <Lieferadresse land="DE"> <Name>Alice Schmid</Name> <Straße>Walnussgasse 42</Straße> <Ort>Frankfurt/Main</Ort> <PLZ>60000</PLZ> </Lieferadresse> <Rechnungsadresse land="DE"> <Name>Robert Schmid</Name> <Straße>Haselnussweg 3</Straße> <Ort>Frankfurt/Main</Ort> <PLZ>61240</PLZ> </Rechnungsadresse> <Kommentar>Bitte mit Geschenkverpackung!</Kommentar> <Waren> <Buch ISBN="3776622148"> <Titel>Vom Glück der Faulheit. Lebensenergie richtig einteilen.</Titel> <Anzahl>1</Anzahl> <PreisEUR>29.90</PreisEUR> <Kommentar>Bitte Liefertermin bis Weihnachten bestätigen.</Kommentar> </Buch> <Buch ISBN="3551551677"> <Titel>Harry Potter und der Stein der Weisen</Titel> <Anzahl>1</Anzahl> <PreisEUR>29.90</PreisEUR> <Lieferdatum>2000-01-04</Lieferdatum> </Buch> </Waren> </Bestellung>
Die Buchbestellung besteht aus einem Hauptelement, Bestellung
, mit den Subelementen Rechnungsadresse
, Lieferadresse
, Kommentar
und Waren
. Außer Kommentar
enthalten allf diese Subelemente wieder andere Subelemente usw., bis ein Subelement, wie PreisEUR
,
eine Zahl anstelle von Subelementen enthält. Elemente, die Subelemente enthalten
oder Attribute tragen, haben so genannte komplexe Typen (complex
types), während Elemente, die nur Zahlen (oder Zeichenketten, ein Datum,
usw.) enthalten, einfache Typen (simple types) haben. Einige
Elemente tragen Attribute; Attribute haben immer einfache Typen.
Die komplexen Typen im Instanzdokument wie auch einige der einfachen Typen sind im Schema für Buchbestellungen definiert. Die anderen einfachen Typen sind als Teil des Vorrats an vordefinierten Typen von XML Schema definiert.
Bevor wir mit der Inspektion des Schemas für Buchbestellungen fortfahren, schweifen wir kurz ab, um die Assoziation von Instanzdokumenten mit dem Schema anzusprechen. Wie Sie bei der Betrachtung des Instanzdokuments sehen können, wird das Schema für Buchbestellungen nirgends erwähnt. Eine Instanz ist nicht dazu verpflichtet, ein Schema zu referenzieren, und obwohl viele Instanzen dies tun werden, haben wir uns dafür entschieden, dieses Kapitel einfach zu halten und anzunehmen, dass jeder, der das Instanzdokument verarbeitet, das Schema dafür ohne Information aus dem Instanzdokument erhalten kann. In späteren Kapiteln werden wir Mechanismen einführen, um ein Instanzdokument explizit mit einem Schema zu assoziieren.
Das Schema für Buchbestellungen ist in der Datei best.xsd definiert:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:annotation> <xsd:documentation xml:lang="DE"> Buchbestellung Schema für Example.com. Copyright 2001 Example.com. Alle Rechte vorbehalten. </xsd:documentation> </xsd:annotation> <xsd:element name="Bestellung" type="BestellungTyp"/> <xsd:element name="Kommentar" type="xsd:string"/> <xsd:complexType name="BestellungTyp"> <xsd:sequence> <xsd:element name="Lieferadresse" type="DeAdresse"/> <xsd:element name="Rechnungsadresse" type="DeAdresse"/> <xsd:element ref="Kommentar" minOccurs="0"/> <xsd:element name="Waren" type="WarenTyp"/> </xsd:sequence> <xsd:attribute name="bestelldatum" type="xsd:date"/> </xsd:complexType> <xsd:complexType name="DeAdresse"> <xsd:sequence> <xsd:element name="Name" type="xsd:string"/> <xsd:element name="Straße" type="xsd:string"/> <xsd:element name="Ort" type="xsd:string"/> <xsd:element name="PLZ" type="xsd:decimal"/> </xsd:sequence> <xsd:attribute name="land" type="xsd:NMTOKEN" fixed="DE"/> </xsd:complexType> <xsd:complexType name="WarenTyp"> <xsd:sequence> <xsd:element name="Buch" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="Titel" type="xsd:string"/> <xsd:element name="Anzahl"> <xsd:simpleType> <xsd:restriction base="xsd:positiveInteger"> <xsd:maxExclusive value="100"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="PreisEUR" type="xsd:decimal"/> <xsd:element ref="Kommentar" minOccurs="0"/> <xsd:element name="Lieferdatum" type="xsd:date" minOccurs="0"/> </xsd:sequence> <xsd:attribute name="ISBN" type="ISBNTyp" use="required"/> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> <xsd:simpleType name="ISBNTyp"> <xsd:restriction base="xsd:string"> <xsd:pattern value="\d{9}[0-9X]"/> <!-- 9 Ziffern gefolgt von einer Prüfziffer im Bereich zwischen 0 und 10 (10 wird als X dargestellt) --> </xsd:restriction> </xsd:simpleType> </xsd:schema>
Das Schema für Buchbestellungen besteht aus einem schema
-Element und einer Reihe von Subelementen, allen voran
element
, complexType
und simpleType
, welche das Erscheinungsbild und den Inhalt von Elementen im Instanzdokument bestimmen.
Jedes Element im Schema hat das Präfix xsd:
, welches über die Deklaration xmlns:xsd="http://www.w3.org/2001/XMLSchema"
beim schema
-Element mit dem XML Schema Namensraum assoziiert ist. Per Konvention wird das Präfix xsd:
verwendet, um den XML Schema Namensraum zu bezeichnen, obwohl auch jedes andere Präfix möglich wäre. Dasselbe Präfix, und
deshalb dieselbe Assoziation, erscheint auch bei den Namen der vordefinierten einfachen Typen, etwa in xsd:string.
Der Zweck der Assoziation ist es, diese Elemente und einfachen Typen dem
XML Schema-Vokabular zuzuordnen und nicht dem Vokabular
des Schema-Autors. Der Klarheit halber benutzen wir im Text nur die Namen
der Elemente und der einfachen Typen und lassen das Präfix
weg, wie etwa bei simpleType
.
In XML Schema gibt es eine grundlegende Unterscheidung zwischen komplexen Typen (complex types), die Elemente enthalten und Attribute tragen dürfen, und einfachen Typen (simple types), bei denen das nicht erlaubt ist. Außerdem gibt es eine wichtige Unterscheidung zwischen Definitionen, die neue Typen (einfach oder komplex) erzeugen, und Deklarationen, die ermöglichen, dass Elemente und Attribute mit speziellen Namen und Typen (einfach oder komplex) in Instanzdokumenten auftreten. In diesem Abschnitt konzentrieren wir uns auf die Definition von komplexen Typen und auf die Deklaration von Elementen und Attributen, die darin auftreten.
Neue komplexe Typen werden mit dem complexType
-Element
definiert. Solche Definitionen enthalten üblicherweise eine Menge von Element-Deklarationen,
Element-Referenzen und Attribut-Deklarationen. Die Deklarationen
sind selbst keine Typen, sondern Assoziationen zwischen einem Namen und den
Beschränkungen (constraints), welche das Auftreten dieses
Namens in Dokumenten regeln, die durch das entsprechende Schema bestimmt
werden. Elemente werden mit dem element
-Element deklariert und Attribute mit dem attribute
-Element. Beispielsweise wird DeAdresse
als komplexer Typ definiert und innerhalb der Definition von DeAdresse
sieht man fünf Element-Deklarationen und eine Attribut-Deklaration.
DeAdresse
-Typs
<xsd:complexType name="DeAdresse"> <xsd:sequence> <xsd:element name="Name" type="xsd:string"/> <xsd:element name="Straße" type="xsd:string"/> <xsd:element name="Ort" type="xsd:string"/> <xsd:element name="PLZ" type="xsd:decimal"/> </xsd:sequence> <xsd:attribute name="land" type="xsd:NMTOKEN" fixed="DE"/> </xsd:complexType>
Die Folge dieser Definition ist, dass jedes Element, das in einer Instanz mit dem Typ DeAdresse
erscheint (im Beispiel in Lieferadresse
und Rechnungsadresse
), aus fünf Elementen und einem Attribut bestehen muss. Diese Elemente müssen Name
, Straße
, Ort
, und PLZ
heißen, wie vom Wert der name
-Attribute
in der Deklaration festgelegt, und sie müssen in der Reihenfolge erscheinen,
in der sie deklariert wurden. Die ersten drei dieser Elemente
müssen alle eine Zeichenkette enthalten und das vierte eine Zahl. Das Element
mit dem Typ DeAdresse
darf ein Attribut namens land
haben, das die Zeichenkette DE
enthalten muss.
Die Definition von DeAdresse
enthält nur Deklarationen mit
einfachen Typen:
string
,
decimal
und
NMTOKEN
. Die Definition von BestellungTyp
dagegen enthält Deklarationen mit komplexen Typen, zum Beispiel DeAdresse
. Beachten Sie jedoch, dass beide Deklarationen dasselbe type
-Attribut verwenden, unabhängig davon, ob der Typ einfach oder komplex ist.
BestellungTyp
<xsd:complexType name="BestellungTyp"> <xsd:sequence> <xsd:element name="Lieferadresse" type="DeAdresse"/> <xsd:element name="Rechnungsadresse" type="DeAdresse"/> <xsd:element ref="Kommentar" minOccurs="0"/> <xsd:element name="Waren" type="WarenTyp"/> </xsd:sequence> <xsd:attribute name="bestelldatum" type="xsd:date"/> </xsd:complexType>
In der Definition von BestellungTyp
gibt es zwei verschiedene Element-Deklarationen, Lieferadresse
und Rechnungsadresse
, die für verschiedene Elemente denselben komplexen Typ (DeAdresse
) verwenden. Die Konsequenz dieser Definition ist, dass jedes Element, das in einem Instanzdokument (z.B. best.xml) erscheint und dessen deklarierter Typ BestellungTyp
ist, aus Elementen mit den Namen Lieferadresse
und Rechnungsadresse
bestehen muss, die jeweils die vier Subelemente (Name
, Straße
, Ort
und PLZ
) enthalten müssen, die als Teil von DeAdresse
deklariert wurden. Die Elemente Lieferadresse
und Rechnungsadresse
dürfen außerdem ein land
-Attribut enthalten, das als Teil von DeAdresse
deklariert wurde.
Die Bestellungtyp
-Definition enthält eine Deklaration für ein bestelldatum
-Attribut, die (wie auch die Deklaration des land
-Attributs) einen einfachen Typ bestimmt. In der Tat muss jedes Attribut einen einfachen Typ referenzieren, denn anders als
Elemente können Attribute keine anderen Elemente oder Attribute enthalten.
Alle bisher beschriebenen Element-Deklarationen haben einen Namen mit einer bestehenden Typdefinition assoziiert. Manchmal ist es jedoch vorzuziehen, ein bestehendes Element zu verwenden, anstatt ein neues zu deklarieren, zum Beispiel:
<xsd:element ref="Kommentar" minOccurs="0" />
Diese Deklaration referenziert ein bestehendes Element, Kommentar
, welches an anderer Stelle im Bestellung-Schema deklariert wurde. Im Allgemeinen muss der Wert des ref
-Attributs ein globales Element referenzieren, also eines, das unterhalb von schema
deklariert wurde und nicht als Teil der Definition eines komplexen Typs. Die Folge der Deklaration im Beispiel ist, dass
in einem Instanzdokument ein Element namens Kommentar
auftreten darf, dessen Inhalt konsistent mit seinem Typ sein muss, in diesem Fall mit string.
Das Kommentar
-Element in BestellungTyp
ist optional, weil der Wert des minOccurs
-Attributs in seiner Deklaration 0 ist. Allgemein muss ein Element erscheinen, wenn der Wert von minOccurs
1 oder größer ist. Die größtmögliche Anzahl, in der ein Element auftreten darf, wird durch den Wert des maxOccurs
-Attributs in seiner Deklaration festgelegt. Dieser Wert kann eine positive ganze Zahl sein, wie etwa 41, oder der Begriff
unbounded
, um anzugeben, dass es keine obere Grenze gibt. Der Vorgabe-Wert für minOccurs
und maxOccurs
ist 1. Wenn also ein Element wie etwa Kommentar
ohne Angabe eines maxOccurs
-Attributs deklariert wird, so darf das Element nicht öfter als einmal auftreten. Wird nur für das minOccurs
-Attribut ein Wert angegeben, muss darauf geachtet werden, dass er kleiner oder gleich dem Vorgabe-Wert des maxOccurs
-Attributs ist, also 0 oder 1. Entsprechend muss, wenn nur ein Wert für das maxOccurs
-Attribut angegeben wird, darauf geachtet werden, dass er größer oder gleich dem Vorgabe-Wert für minOccurs
ist, also 1 oder größer. Werden beide Attribute weggelassen, muss das Element genau einmal auftreten.
Attribute dürfen einmal oder keinmal auftreten, jedoch
nicht in anderen Häufigkeiten, weshalb die Syntax für die Spezifikation
von Häufigkeitsbeschränkungen bei Attributen von der
Syntax für Elemente abweicht. Insbesondere können Attribute mit einem
use
-Attribut deklariert werden, um festzulegen, ob ein Attribut vorgeschrieben (Wert required
, beispielsweise bei der Deklaration des ISBN
-Attributs in best.xsd), optional
oder sogar verboten (Wert prohibited
) ist.
Vorgabe-Werte für Attribute und Elemente werden mit dem default
-Attribut
deklariert, auch wenn es für Attribute und Elemente geringfügig verschiedene
Konsequenzen hat. Wenn ein Attribut mit einem Vorgabe-Wert
deklariert wird, ist sein Wert der im Instanzdokument angegebene Wert. Wenn
das Attribut im Instanzdokument nicht erscheint, fügt
der Schema-Prozessor als Wert den Wert des default
-Attributs ein. Beachten Sie, dass Vorgabe-Werte für Attribute nur dann sinnvoll sind, wenn das Attribut selbst optional ist.
Es ist deshalb ein Fehler, einen Vorgabe-Wert zu spezifizieren, wenn das use
-Attribut einen anderen Wert als optional
hat.
Der Schema-Prozessor behandelt Elemente mit Vorgabe-Wert
etwas anders. Wenn ein Element mit Vorgabe-Wert deklariert wird,
ist sein Wert der im Instanzdokument als sein Inhalt angegebene
Wert. Wenn das Element im Instanzdokument ohne Inhalt auftritt,
fügt der Schema-Prozessor den Wert des default
-Attributs
ein. Tritt das Element jedoch gar nicht auf, fügt der Schema-Prozessor auch
nichts ein. Der Unterschied zwischen Vorgabe-Werten
für Elemente und für Attribute kann folgendermaßen zusammengefasst werden:
Vorgabe-Werte für Attribute werden angewendet, wenn
das Attribut fehlt, und Vorgabe-Werte für Elemente, wenn das Element leer
ist.
Das Attribut fixed
wird in Deklarationen von Elementen und Attributen verwendet, um sicherzustellen, dass das betreffende Element oder Attribut
einen bestimmten Wert hat. Beispielsweise enthält best.xsd eine Deklaration für das land
-Attribut, welches mit dem festen Vorgabewert fixed
DE
spezifiziert ist. Diese Deklaration bedeutet, dass das land
-Attribut in Instanzdokumenten optional ist (der Vorgabe-Wert von use
ist optional
), aber wenn es erscheint, muss sein Wert DE
sein, und wenn es nicht erscheint, wird es der Schema-Prozessor mit dem Wert DE
einfügen. Beachten Sie, dass die Konzepte eines festen Vorgabewerts und eines Vorgabe-Werts sich gegenseitig ausschließen.
Deshalb ist es ein Fehler, wenn eine Deklaration ein fixed
- und ein default
-Attribut enthält.
Die Werte der Attribute, die in Element- und Attribut-Deklarationen verwendet werden, um die Häufigkeit des Auftretens einzuschränken, sind in Tabelle 1 zusammengefasst.
Tabelle 1. Häufigkeitsbeschränkungen für Elemente und Attribute | ||
---|---|---|
Elemente (minOccurs, maxOccurs) fixed, default | Attribute use, fixed, default | Anmerkungen |
(1, 1) -, - | required, -, - | Element/Attribut muss genau einmal auftreten, der Wert ist beliebig. |
(1, 1) 37, - | required, 37, - | Element/Attribut muss genau einmal auftreten, der Wert muss 37 sein. |
(2, unbounded) 37, - | nicht anwendbar | Element/Attribut muss zweimal oder öfter auftreten, der Wert muss 37 sein; allgemein müssen die Werte von minOccurs und maxOccurs positive ganze Zahlen sein, der Wert von maxOccurs darf auch "unbounded" (unbeschränkt) sein. |
(0, 1) -, - | optional, -, - | Element/Attribut darf höchstens einmal auftreten, der Wert ist beliebig. |
(0, 1) 37, - | optional, 37, - | Element/Attribut darf höchstens einmal auftreten, wenn es auftritt, muss der Wert 37 sein, ansonsten wird 37 angenommen. |
(0, 1) -, 37 | optional, -, 37 | Element/Attribut darf höchstens einmal auftreten, wenn es nicht auftritt, ist der Wert 37, ansonsten der gegebene Wert. |
(0, 2) -, 37 | nicht anwendbar | Element darf höchstens zweimal auftreten, wenn es nicht auftritt, wird nichts eingefügt. Wenn es auftaucht, aber leer ist, ist sein Wert 37, ansonsten der gegebene Wert. Allgemein dürfen die Werte für minOccurs und maxOccurs positive ganze Zahlen sein und der Wert von maxOccurs zusätzlich "unbounded" (unbeschränkt). |
(0, 0) -, - | prohibited, -, - | Element/Attribut darf nicht auftreten. |
Beachten Sie, dass weder minOccurs noch maxOccurs noch use in der Deklaration von globalen Attributen oder Elementen auftreten dürfen. |
Globale Elemente und Attribute werden durch Deklarationen erzeugt, die als Kind des schema
-Elements erscheinen. Nach ihrer Deklaration können globale Elemente und Attribute, wie bereits beschrieben, in einer oder
mehreren Deklarationen über das ref
-Attribut referenziert werden. Eine Deklaration, die ein globales Element referenziert, bewirkt, dass das referenzierte Element
im Instanzdokument im Kontext der referenzierenden Deklaration auftreten darf. So darf beispielsweise das Kommentar
-Element in best.xml auf derselben Ebene wie Lieferadresse
, Rechnungsadresse
und Waren
auftreten, weil die Deklaration, die Kommentar
referenziert, in der Definition des komplexen Typs auf derselben Ebene erscheint
wie die Deklarationen der anderen drei Elemente.
Die Deklaration eines globalen Elements ermöglicht außerdem,
dass das Element im Instanzdokument auf oberster Ebene (Top Level)
erscheint. Folglich darf Bestellung
, weil es in best.xsd als globales Element deklariert wurde, in best.xml als oberstes Element auftreten. Mit derselben Argumentation darf auch ein Kommentar
-Element in einem Instanzdokument wie best.xml auf oberster Ebene stehen.
Es gibt eine Reihe von Einschränkungen bei der Verwendung
von globalen Elementen und Attributen. Eine ist, dass globale Deklarationen
keine Referenzen enthalten dürfen, sie müssen einfache
wie komplexe Typen direkt benennen. Genauer gesagt, globale Deklarationen
dürfen das ref
-Attribut nicht enthalten, sie müssen das type
-Attribut verwenden (oder, wie weiter unten beschrieben, die Definition eines anonymen Typs
enthalten). Eine zweite Einschränkung ist, dass die
Kardinalität globaler Elemente und Attribute nicht beschränkt werden kann,
wohl aber die Kardinalität lokaler Elemente/Attribute,
die eine globale Deklaration referenzieren. Mit anderen Worten, globale Deklarationen
dürfen die Attribute minOccurs
, maxOccurs
und use
nicht enthalten.
Bislang haben wir beschrieben, wie man neue komplexe Typen definiert (z.B. BestellungTyp
), Elemente deklariert (z.B. Bestellung
) und Attribute deklariert (z.B. bestelldatum
).
Diese Aktivitäten schließen normalerweise die Namensgebung ein und so ergibt
sich folgende Frage: Was passiert, wenn man zwei Dingen
denselben Namen gibt? Die Antwort hängt davon ab, um was für Dinge es sich
handelt. Im Allgemeinen ist die Wahrscheinlichkeit,
dass es einen Konflikt gibt, umso größer, je ähnlicher die Dinge sind.
Hier einige Beispiele, um darzustellen, wann gleiche Namen
problematisch sind. Sind beide Dinge Typen (etwa wenn man einen
komplexen Typ mit Namen OrtTyp
und einen einfachen Typ mit demselben Namen definiert) gibt es einen Konflikt.
Wenn die zwei Dinge ein Typ und ein Element oder Attribut sind (etwa wenn man einen komplexen Typ namens DeAdresse
definiert und ein Element namens DeAdresse
deklariert) gibt es keinen Konflikt. Wenn die zwei
Dinge Elemente innerhalb verschiedener Typen sind (also keine globalen Elemente),
etwa wenn man ein Element namens Titel
(als Teil des Namens) innerhalb von DeAdresse
und ein weiteres Element namens Titel
innerhalb von Buch
definiert, gibt es keinen Konflikt. (Solche Elemente nennt man manchmal lokale
Element-Deklarationen.) Schließlich gibt es noch den
Fall, dass beide Dinge Typen sind, von denen man einen selbst definiert hat
und der andere ein vordefinierter Typ von XML Schema
ist, etwa wenn man einen Typ namens decimal
definiert. Hierbei gibt es keinen Konflikt. Dieser scheinbare Widerspruch
klärt sich dadurch auf, dass die beiden Typen zu verschiedenen
Namensräumen gehören. Auf die Verwendung von Namensräumen in XML Schema
werden wir in einem späteren Kapitel eingehen.
Das Buchbestellung-Schema deklariert einige Elemente und
Attribute, die einfache Typen haben. Einige dieser einfachen Typen,
wie string
und decimal
, sind in XML Schema vordefiniert, während andere
von den vordefinierten Typen abgeleitet sind. So hat zum Beispiel
das ISBN
-Attribut einen Typ namens ISBNTyp
, der von
string
abgeleitet ist. Sowohl die vordefinierten als auch
davon abgeleitete Typen können in allen Element- und Attribut-Deklarationen
verwendet werden. Tabelle 2 listet alle in XML Schema vordefinierten einfachen Typen auf, zusammen mit Beispielen für die einzelnen Typen.
Tabelle 2. Vordefinierte einfache Typen in XML Schema | ||
---|---|---|
Einfacher Typ (Simple Type) | Beispiele (durch Kommata getrennt) | Anmerkungen |
string | Bitte mit Geschenkverpackung! | |
normalizedString | Bitte mit Geschenkverpackung! | siehe (3) |
token | Bitte mit Geschenkverpackung! | siehe (4) |
byte | -1, 126 | siehe (2) |
unsignedByte | 0, 126 | siehe (2) |
base64Binary | GpM7 | |
hexBinary | 0FB7 | |
integer | -126789, -1, 0, 1, 126789 | siehe (2) |
positiveInteger | 1, 126789 | siehe (2) |
negativeInteger | -126789, -1 | siehe (2) |
nonNegativeInteger | 0, 1, 126789 | siehe (2) |
nonPositiveInteger | -126789, -1, 0 | siehe (2) |
int | -1, 126789675 | siehe (2) |
unsignedInt | 0, 1267896754 | siehe (2) |
long | -1, 12678967543233 | siehe (2) |
unsignedLong | 0, 12678967543233 | siehe (2) |
short | -1, 12678 | siehe (2) |
unsignedShort | 0, 12678 | siehe (2) |
decimal | -1.23, 0, 123.4, 1000.00 | siehe (2) |
float | -INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN | äquivalent zu single-precision 32-bit floating point, NaN steht für "not a number" (keine Zahl), siehe (2) |
double | -INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN | äquivalent zu double-precision 64-bit floating point, siehe (2) |
boolean | true, false,1, 0 | |
time | 13:20:00.000, 13:20:00.000-05:00 | siehe (2) |
dateTime | 1999-05-31T13:20:00.000-05:00 | 31. Mai 1999 um 13 Uhr 20, Eastern Standard Time (EST ist 5 Stunden hinter UTC (Koordinierte Universalzeit), siehe (2)) |
duration | P1Y2M3DT10H30M12.3S | 1 Jahr, 2 Monate, 3 Tage, 10 Stunden, 30 Minuten und 12,3 Sekunden |
date | 1999-05-31 | siehe (2) |
gMonth | --05-- | Mai, siehe (2) und (5) |
gYear | 1999 | 1999, siehe (2) (5) |
gYearMonth | 1999-02 | Februar 1999, egal wie viele Tage er hat, siehe (2) und (5) |
gDay | ---31 | Der 31., siehe (2) und (5) |
gMonthDay | --05-31 | Jeder 31ste Mai, siehe (2) und (5) |
Name | Lieferadresse | XML 1.0 Name-Typ |
QName | best:DeAdresse | XML Namespace QName |
NCName | DeAdresse | XML Namespace NCName, d.h. ein QName ohne Präfix und Doppelpunkt |
anyURI | http://www.example.com/, http://www.example.com/doc.html#ID5 | |
language | en-GB, en-US, fr | Gültige Werte für xml:lang sind in XML 1.0 definiert. |
ID | XML 1.0 ID Attribut-Typ, siehe (1) | |
IDREF | XML 1.0 IDREF Attribut-Typ, siehe (1) | |
IDREFS | XML 1.0 IDREFS Attribut-Typ, siehe (1) | |
ENTITY | XML 1.0 ENTITY Attribut-Typ, siehe (1) | |
ENTITIES | XML 1.0 ENTITIES Attribut-Typ, siehe (1) | |
NOTATION | XML 1.0 NOTATION Attribut-Typ, siehe (1) | |
NMTOKEN | US, Brésil | XML 1.0 NMTOKEN Attribut-Typ, siehe (1) |
NMTOKENS | US UK, Brésil Canada Mexique | XML 1.0 NMTOKENS Attribut-Typ, d.h. eine durch Leerraum getrennte Liste von NMTOKEN, siehe (1) |
Anmerkungen:
(1) Um die Kompatibilität zwischen XML Schema
und XML 1.0 DTDs zu bewahren, sollten die einfachen Typen ID, IDREF, IDREFS,
ENTITY, ENTITIES, NOTATION, NMTOKEN und NMTOKENS
nur für Attribute verwendet werden. (2) Der Wert
dieses Typs kann durch mehrere lexikalische Formate repräsentiert werden;
so sind beispielsweise sowohl 100 als auch 1.0E2
gültige Gleitkommaformate für “einhundert”. Es
gibt jedoch für diesen Wert Regeln, die ein kanonisches lexikalisches Format
definieren, siehe XML Schema Teil 2.
(3) Die Zeichen für Zeilenvorschub (Newline),
Tabulator und Zeilenanfang (Carriage Return) werden im Typ normalizedString vor der Verarbeitung durch einen Schema-konformen Prozessor in Leerzeichen umgewandelt.
(4) In normalizedString werden benachbarte Leerzeichen in ein einzelnes Leerzeichen umgewandelt, sowie führende und nachfolgende Leerzeichen entfernt.
(5) Das "g"-Präfix kennzeichnet Zeiträume im gregorianischen Kalender.
|
Neue einfache Typen werden durch Ableitung von bestehenden
einfachen Typen (vordefiniert oder abgeleitet) definiert. Insbesondere
kann man einen neuen einfachen Typ durch Einschränkung eines
bestehenden einfachen Typs ableiten. Mit anderen Worten, die
erlaubte Wertemenge des neuen Typs ist eine Untermenge der Wertemenge
des bestehenden Typs. Um den neuen einfachen Typ zu definieren
und zu benennen, wird das simpleType
-Element verwendet. Das restriction
-Element wird verwendet, um den bestehenden (Basis-)Typ anzugeben und um die “Fassetten” (facets) zu bestimmen, welche die
Wertemenge einschränken. Eine komplette Liste der Fassetten ist in Anhang B zu finden.
Angenommen, wir wollen einen neuen Typ von ganzen Zahlen mit Namen meinInteger
erzeugen, dessen Wertebereich zwischen 10000 und 99999 (inklusive) liegt. meinInteger
soll auf dem vordefinierten Typ
integer
basieren, dessen Wertebereich auch ganze Zahlen enthält,
die kleiner als 10000 oder größer als 99999 sind. Um meinInteger
zu definieren, schränken wir den Wertebereich des Basistyps
integer
ein, indem wir zwei Fassetten namens minInclusive
und maxInclusive
anwenden:
<xsd:simpleType name="meinInteger"> <xsd:restriction base="xsd:integer"> <xsd:min-inclusive value="10000"/> <xsd:max-inclusive value="99999"/> </xsd:restriction> </xsd:simpleType>
Das Beispiel greift nur eine einzelne Kombination eines Basistyps mit zwei Fassetten heraus, um meinInteger
zu definieren, aber ein Blick in die Liste der vordefinierten einfachen Typen und ihrer Fassetten (Anhang B) zeigt, dass es noch viele andere sinnvolle Kombinationen gibt.
Das Schema für Buchbestellungen enthält ein weiteres,
ausführlicheres Beispiel für die Definition eines einfachen Typs. Ein
neuer einfacher Typ namens ISBNTyp
wird (mittels Einschränkung) vom einfachen Typ
string
abgeleitet. Außerdem werden die Werte für ISBNTyp
über eine Fassette namens
pattern
(Muster) in Verbindung mit einem regulären Ausdruck “\d{9}[0-9X]
”, lies “neun Ziffern gefolgt von einem Zeichen aus dem Bereich 0 bis 9 und X”, eingeschränkt.
ISBNTyp
<xsd:simpleType name="ISBNTyp"> <xsd:restriction base="xsd:string"> <xsd:pattern value="\d{9}[0-9X]"/> </xsd:restriction> </xsd:simpleType>
Die Sprache für reguläre Ausdrücke wird in Anhang D ausführlicher beschrieben.
Insgesamt definiert XML Schema 15 Fassetten, die in Anhang B aufgeführt sind. Besonders nützlich ist die enumeration
-Fassette (Aufzählung): Sie kann benutzt werden, um die Werte fast jeden einfachen Typs (außer
boolean) zu beschränken. Die enumeration
-Fassette beschränkt einfache Typen auf eine wohldefinierte Menge zugelassener Werte. Man könnte beispielsweise diese Fassette
dazu verwenden, einen neuen einfachen Typ Bundesland
zu definieren, der von
string
abgeleitet ist und als Wert den Namen eines deutschen Bundeslandes haben muss:
<xsd:simpleType name="Bundesland"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="Baden-Württemberg"/> <xsd:enumeration value="Bayern"/> <xsd:enumeratin value="Berlin"/> <!-- usw. --> <xsd:enumeration value="Thüringen"/> </xsd:restriction> </xsd:simpleType>
Bundesland
wäre in einem Schema eine wesentlich bessere Typ-Wahl für ein Bundesland-Element als
string
, da Bundesland
den Inhalt des Elements auf sinnvolle Werte einschränkt. Zu beachten ist,
dass die Werte in einer Aufzählung für einen bestimmten
Typ eindeutig sein müssen.
Zusätzlich zu den so genannten atomaren Typen, welche die meisten der in Tabelle 2
aufgeführten Typen ausmachen, kennt XML Schema das Konzept der Listentypen.
(Atomare Typen, Listentypen und die im nächsten Abschnitt
beschriebenen Vereinigungstypen bilden zusammen die einfachen Typen.) Aus
dem Blickwinkel von XML Schema ist der Wert eines atomaren
Typs unteilbar. Beispielsweise ist der NMTOKEN-Wert DE
unteilbar in dem Sinne, dass kein Teil von DE
, wie etwa das Zeichen “D
”, alleine eine Bedeutung hat. Im Gegensatz dazu bestehen Listentypen aus einer Folge von atomaren Typen, und folglich sind
die Teile der Folge (die “Atome”) selbst bedeutungsvoll. Zum Beispiel ist
NMTOKENS
ein Listentyp und ein Element dieses Typs wäre eine durch Leerraum getrennte Liste von
NMTOKEN-Elementen, wie etwa “DE US GB
”. XML Schema hat drei vordefinierte Listentypen, nämlich
NMTOKENS
,
IDREFS
und
ENTITIES.
Zusätzlich zur Verwendung der vordefinierten Listentypen kann man neue Listentypen durch Ableitung von bestehenden atomaren Typen erzeugen. (Man kann keine Listentypen aus anderen Listentypen erzeugen, genausowenig wie aus komplexen Typen.) Eine Liste von ganzen Zahlen wird zum Beispiel so definiert:
meinIntegerListe
<xsd:simpleType name="meinIntegerListe"> <xsd:list itemType="meinInteger"/> </xsd:simpleType>
Ein Element in einem Instanzdokument, dessen Inhalt dem Typ meinIntegerListe
entspricht, wäre:
<meineIntegers>89073 53229 10000 10178</meineIntegers>
Auf Listentypen können mehrere Fassetten angewendet werden: length
, minLength
, maxLength
und enumeration
. Um beispielsweise eine Liste von genau sechs Bundesländern (SechsBundesländer
) zu definieren, definieren wir zuerst einen neuen Listentyp namens BundesländerListe
aus Bundesland
und leiten daraus SechsBundesländer
ab, indem wir BundesländerListe
auf sechs Einträge beschränken:
<xsd:simpleType name="BundeslandListe"> <xsd:list itemType="Bundesland"/> </xsd:simpleType> <xsd:simpleType name="SechsBundesländer"> <xsd:restriction base="BundeslandListe"> <xsd:length value="6"/> </xsd:restriction> </xsd:simpleType>
Elemente vom Typ SechsBundesländer
müssen sechs Einträge haben, von denen jeder einer der (atomaren) Werte des Listentyps Bundesland
sein muss, zum Beispiel:
<sechsLänder>Sachsen Baden-Württemberg Rheinland-Pfalz Brandenburg Niedersachsen Hessen</sechsLänder>
Beachten Sie, dass es möglich ist, einen Listentyp vom vordefinierten Typ string abzuleiten. string darf jedoch Leerraum enthalten und Leerraum trennt die Einträge einer Liste. Man sollte also bei der Benutzung von Listentypen mit dem Basistyp string vorsichtig sein. Wenn man beispielsweise einen Listentyp mit Länge drei und dem Basistyp string definiert, dann ist folgende Liste mit drei Einträgen erlaubt:
Europa Amerika Afrika
Folgende Liste mit drei “Einträgen” dagegen ist nicht erlaubt:
Europa Amerika Nord Amerika
Obwohl “Nord Amerika
”
außerhalb der Liste als eine Zeichenkette möglich ist, erzeugt der Leerraum
innerhalb der Liste effektiv einen vierten Eintrag,
weshalb das zweite Beispiel keine gültige Instanz des Typs mit drei Einträgen
ist.
Mit atomaren Typen und Listentypen können Elemente
oder Attribute als Wert eine oder mehrere Instanzen eines atomaren Typs
haben. Im Gegensatz dazu können
Elemente oder Attribute mit Vereinigungstypen (Union) als Wert eine oder
mehrere Instanzen eines Typs haben, der selbst aus der
Vereinigungsmenge mehrerer atomarer Typen und Listentypen besteht. Zur Verdeutlichung
erzeugen wir einen Vereinigungstyp für die Repräsentation
von Bundesländern entweder durch den Namen des Landes oder als Menge von
Postleitzahlen. Der Vereinigungstyp Land_meinInteger_Union
ist aus einem atomaren Typ und einem Listentyp zusammengesetzt:
<xsd:simpleType name="Land_meinInteger_Union"> <xsd:union memberTypes="Bundesland meinInteger"/> </xsd:simpleType>
Bei der Definition eines Vereinigungstyps ist der Wert des memberTypes
-Attributs eine Liste aller Typen, über deren Wertebereich vereinigt wird.
Angenommen, wir haben ein Element namens PLZs
vom Typ Land_meinInteger_Union
deklariert. Dann sind folgendes gültige Instanzen dieses Elements:
<PLZs>Bayern</PLZs> <PLZs>65454 21542 44441 11451 80331</PLZs> <PLZs>Thüringen</PLZs> <PLZs>Bayern 21542 Thüringen 11451</PLZs>
Auf Vereinigungstypen können zwei Fassetten angewendet werden, pattern
und enumeration
.
Schemata können aufgebaut werden, indem man Mengen von benannten Typen definiert, wie etwa Bestellungtyp
, und dann Elemente deklariert, die diese Typen mit der type=
-Konstruktion referenzieren, wie etwa das Element Bestellung
.
Dieser Stil der Schema-Erstellung ist direkt, kann aber
unhandlich sein, besonders wenn man viele Typen definiert, die nur
einmal referenziert werden und nur wenige Beschränkungen enthalten.
Für diese Fälle kann der Typ kurz und bündig als anonymer
Typ definiert werden, was den zusätzlichen Aufwand für das Benennen und
explizite Referenzieren einspart.
Die Definition des Typs WarenTyp
in best.xsd enthält zwei Element-Deklarationen, die anonyme Typen verwenden (Buch
und Anzahl
). Allgemein sind anonyme Typen durch das Fehlen eines type
-Attributs in der Deklaration eines Elements oder Attributs gekennzeichnet. An seiner Stelle steht die Deklaration eines nicht
benannten (einfachen oder komplexen) Typs:
<xsd:complexType name="WarenTyp"> <xsd:sequence> <xsd:element name="Buch" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="Titel" type="xsd:string" /> <xsd:element name="Anzahl"> <xsd:simpleType> <xsd:restriction base="xsd:positiveInteger"> <xsd:maxExclusive value="100"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="PreisEUR" type="xsd:decimal"/> <xsd:element ref="Kommentar" minOccurs="0"/> <xsd:element name="Lieferdatum" type="xsd:date" minOccurs="0"/> </xsd:sequence> <xsd:attribute name="ISBN" type="ISBNTyp" use="required"/> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType>
Im Fall des Buch
-Elements ist es ein anonymer komplexer Typ mit den Elementen Titel
, Anzahl
, PreisEUR
, Kommentar
und Lieferdatum
und dem Attribut ISBN
. Im Fall des Anzahl
-Elements ist es ein anonymer einfacher Typ, der von
integer
abgeleitet ist und dessen Werte im Bereich zwischen 1 und 99 liegen.
Das Schema für Buchbestellungen enthält viele Beispiele für Elemente, die andere Elemente enthalten (z.B. Waren
), Elemente, die Attribute haben und andere Elemente enthalten (z.B. Lieferadresse
), und Elemente, die nur einen Wert mit einfachem Typ enthalten (z.B. PreisEUR
).
Wir haben jedoch weder Elemente gesehen, die Attribute haben, aber einen
Wert mit einfachem Typ enthalten, noch Elemente, die andere
Elemente gemischt mit Zeichendaten enthalten, noch Elemente, die gar keinen
Inhalt haben. In diesem Abschnitt werden wir auf diese
Variationen des Inhaltsmodells von Elementen näher eingehen.
Als Erstes betrachten wir die Deklaration eines Elements, das ein Attribut hat und einen einfachen Wert enthält. In einem Instanzdokument könnte so ein Element folgendermaßen aussehen:
<PreisInternational währung="EUR">422.46</PreisInternational>
Das Schema für Buchbestellungen deklariert ein PreisEUR
-Element, das den Ausgangspunkt bildet:
<xsd:element name="PreisEUR" type="xsd:decimal" />
Wie fügen wir diesem Element jetzt Attribute hinzu? Wie bereits erwähnt können einfache Typen keine Attribute haben und decimal ist ein einfacher Typ. Wir müssen also einen komplexen Typ deklarieren, der die Attribut-Deklaration trägt. Außerdem soll der Inhalt den einfachen Typ decimal haben. Aus unserer ursprünglichen Frage wird also: Wie definiert man einen komplexen Typ, der auf dem einfachen Typ decimal aufbaut? Die Antwort ist, einen neuen komplexen Typ vom einfachen Typ decimalabzuleiten:
<xsd:element name="PreisInternational"> <xsd:complexType> <xsd:simpleContent> <xsd:extension base="xsd:decimal"> <xsd:attribute name="währung" type="xsd:string"/> </xsd:extension> </xsd:simpleContent> </xsd:complexType> </xsd:element>
Wir verwenden das complexType
-Element, um die Definition eines neuen (anonymen) Typs einzuleiten. Um anzugeben, dass das Inhaltsmodell des neuen Typs
nur Zeichendaten und keine Elemente enthält, verwenden wir das simpleContent
-Element. Und schließlich leiten wir den neuen Typ durch Erweiterung des einfachen Typs
decimal
ab. Die Erweiterung besteht im Hinzufügen des Attributs währung
mit einer normalen Attribut-Deklaration. (Die Ableitung von Typen wird in Kapitel 4 genauer erläutert.) Das auf diese Weise deklarierte PreisInternational
-Element sieht in Instanzen so aus, wie im Beispiel am Anfang dieses Abschnitts gezeigt.
Der Aufbau des Schemas für Buchbestellungen wird durch Elemente charakterisiert, die Subelemente enthalten, wobei die am tiefsten geschachtelten Subelemente Zeichendaten enthalten. XML Schema erlaubt daneben noch die Erstellung von Schemata, bei denen Zeichendaten auf derselben Ebene wie Subelemente auftreten können und nicht auf die am tiefsten geschachtelten Subelemente beschränkt sind.
Betrachten Sie zur Veranschaulichung folgenden Ausschnitt aus einem Brief an einen Kunden, der einige der Elemente aus dem Bestellungs-Schema verwendet:
<BriefText> <Anrede>Sehr geehrter Herr <Name>Schmid</Name>,</Anrede> Ihre Bestellung von <Anzahl>1</Anzahl> <Buchtitel>Herr der Ringe</Buchtitel> wurde am <Lieferdatum>1999-05-21</Lieferdatum> ausgeliefert. ... </BriefText>
Beachten Sie, dass Text zwischen Elementen und deren
Subelementen erscheint. Genauer gesagt, der Text erscheint zwischen den
Elementen Anrede
, Anzahl
, Buchtitel
und Lieferdatum
, allesamt Kindelemente von BriefText
. Der folgende Teil eines Schemas deklariert BriefText
:
<xsd:element name="BriefText"> <xsd:complexType mixed="true"> <xsd:sequence> <xsd:element name="Anrede"> <xsd:complexType mixed="true"> <xsd:sequence> <xsd:element name="Name" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="Anzahl" type="xsd:positiveInteger"/> <xsd:element name="Buchtitel" type="xsd:string"/> <xsd:element name="Lieferdatum" type="xsd:date"/> <!-- usw. --> </xsd:sequence> </xsd:complexType> </xsd:element>
Die Elemente werden mit der element
-Konstruktion deklariert und ihre Typen mit der complexType
-Konstruktion definiert, genau wie zuvor beschrieben. Um Zeichendaten zwischen den Kindelementen von BriefText
zu erlauben, wird lediglich das mixed
-Attribut auf true
gesetzt.
Beachten Sie, dass sich das mixed
-Modell in XML Schema grundlegend vom mixed-Modell in XML 1.0
unterscheidet. Beim gemischten Inhaltsmodell von XML Schema müssen Ordnung
und Anzahl der Kindelemente in einer Instanz mit der
im Schema spezifizierten Ordnung und Anzahl der Kindelemente übereinstimmen.
Im Gegensatz dazu kann beim gemischten Inhaltsmodell
von XML 1.0 die Ordnung und Anzahl der Kindelemente in einer Instanz nicht
beschränkt werden. Kurz gesagt, mit XML Schema ist die
vollständige Validierung von gemischten Inhaltsmodellen möglich, während
bei XML 1.0 nur teilweise validiert werden kann.
Angenommen, wir wollen, dass das PreisInternational
-Element sowohl die Währungseinheit als auch den Preis als Attributwert enthält statt als separate Attribut- und Inhaltswerte.
Im Beispiel:
<PreisInternational währung="EUR" wert="423.46"/>
Solch ein Element hat überhaupt keinen Inhalt: Sein Inhaltsmodell ist leer. Um einen Typ mit leerem Inhaltsmodell zu definieren, definieren wir in Wirklichkeit einen Typ, der nur Elemente als Inhalt erlaubt, aber dann keine Elemente definiert; das Inhaltsmodell des Typs ist also leer:
<xsd:element name="PreisInternational"> <xsd:complexType> <xsd:complexContent> <xsd:restriction base="xsd:anyType"> <xsd:attribute name="währung" type="xsd:string"/> <xsd:attribute name="wert" type="xsd:decimal"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> </xsd:element>
In diesem Beispiel definieren wir einen (anonymen) Typ mit komplexem Inhalt (complexContent
), also nur mit Elementen. Das Element complexContent
signalisiert, dass wir das Inhaltsmodell eines komplexen Typs einschränken oder erweitern wollen, und die Einschränkung (restriction
) von anyType
deklariert zwei Attribute, aber keinen Element-Inhalt (für mehr Informationen über Einschränkung, siehe Kapitel 4.4). Das so deklarierte Element PreisInternational
darf in einer Instanz legitim wie im obigen Beispiel gezeigt auftreten.
Die vorige Syntax für ein Element ohne Inhalt ist relativ ausschweifend; man kann das PreisInternational
-Element auch kompakter definieren:
<xsd:element name="PreisInternational"> <xsd:complexType> <xsd:attribute name="währung" type="xsd:string"/> <xsd:attribute name="wert" type="xsd:decimal"/> </xsd:complexType> </xsd:element>
Diese kompakte Syntax funktioniert, weil die Definition eines komplexen Typs, die weder ein simpleContent
- noch ein complexContent
-Element enthält, als Abkürzung für eine Definition, die anyType
einschränkt, interpretiert wird.
Der anyType
repräsentiert die Abstraktion des ur-type, dem Basistyp, von dem alle einfachen und komplexen Typen abgeleitet sind. Ein anyType
schränkt seinen Inhalt in keiner Weise ein. Er kann wie jeder andere Typ verwendet werden:
<xsd:element name="irgendwas" type="xsd:anyType"/>
Der Inhalt des so deklarierten Elements ist in keiner Weise eingeschränkt,
der Wert des Elements könnte also 423.46
sein, aber es könnte genauso gut jede andere Zeichenkette oder sogar eine Mischung aus Zeichen und Elementen sein. Tatsächlich
ist anyType
der Default-Typ, wenn kein Typ angegeben wird. Also könnte das Beispiel auch folgendermaßen geschrieben werden:
<xsd:element name="irgendwas"/>
An Stellen, wo uneingeschränkter Element-Inhalt benötigt wird, etwa
im Fall eines Elements, das Prosa enthält, in die Markup
für Internationalisierung eingebettet werden muss, kann die Default-Deklaration
oder eine geringfügig eingeschränkte Variante davon
durchaus angebracht sein. Der in Abschnitt 5.5 beschriebene Text
-Typ ist ein Beispiel für einen Typ, der für so einen Zweck geeignet wäre.
XML Schema kennt drei Elemente, um Schemata mit Anmerkungen
zu versehen, die sowohl menschlichen Lesern als auch Anwendungen
das Leben leichter machen. Im Schema für Buchbestellungen verwenden
wir das documentation
-Element für eine kurze Beschreibung des Schemas und für Copyright-Informationen. Für Material, das von Menschen gelesen werden
soll, empfehlen wir das Element documentation
. Wir schlagen vor, das xml:lang
-Attribut damit zu verwenden, um die Sprache, in der der Text verfasst ist, anzugeben. Alternativ dazu kann man mit einem
xml:lang
-Attribut auf dem schema
-Element die Sprache für die gesamte Information im Schema angeben.
Das appInfo
-Element,
im Schema für Buchbestellungen nicht verwendet, kann angewandt werden, um
Informationen für Hilfsprogramme, Stylesheets oder andere
Anwendungen unterzubringen. Ein interessantes Beispiel
für die Verwendung von appInfo
ist ein Schema, das die einfachen Typen in “XML Schema Teil 2: Datentypen”
beschreibt. Die Information darüber, welche Fassetten auf
welche Typen angewendet werden dürfen, ist in appInfo
-Elementen repräsentiert und wurde von einer Anwendung dazu benutzt, den Text für den entsprechenden Abschnitt des “XML Schema
Teil 2”-Dokuments automatisch zu erzeugen.
Sowohl documentation
als auch appInfo
erscheinen als Subelemente von annotation
, welches wiederum am Anfang der meisten Schema-Konstrukte erscheinen darf. Zur Verdeutlichung zeigt das folgende Beispiel
annotation
-Elemente am Anfang einer Element-Deklaration und am Anfang der Definition eines komplexen Typs:
<xsd:element name="PreisInternational"> <xsd:annotation> <xsd:documentation xml:lang="DE"> Element-Deklaration mit anonymem Typ </xsd:documentation> </xsd:annotation> <xsd:complexType> <xsd:annotation> <xsd:documentation xml:lang="DE"> leerer anonymer Typ mit 2 Attributen </xsd:documentation> </xsd:annotation> <xsd:complexContent> <xsd:restriction base="xsd:anyType"> <xsd:attribute name="währung" type="xsd:string"/> <xsd:attribute name="wert" type="xsd:decimal"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> </xsd:element>
Das annotation
-Element darf auch am Anfang anderer Schema-Konstrukte stehen, etwa bei denen, die durch die Elemente schema
, simpleType
und attribute
gekennzeichnet werden.
Die Definitionen der komplexen Typen im Schema für Buchbestellungen
deklarieren alle Sequenzen von Elementen, die im Instanzdokument
erscheinen müssen. Das Auftreten der einzelnen im so genannten
Inhaltsmodell dieser Typen deklarierten Elemente kann optional
sein, wie durch den Wert 0 für das Attribut minOccurs
angezeigt (z.B. bei Kommentar
), oder es kann anderweitig eingeschränkt sein, je nach den Werten von minOccurs
und maxOccurs
.
XML Schema kennt auch Beschränkungen, die sich auf Gruppen von Elementen
im Inhaltsmodell beziehen. Diese Beschränkungen spiegeln
die in XML 1.0 verfügbaren Beschränkungen wider, XML Schema bietet aber noch
einige zusätzliche Beschränkungen. Beachten Sie, dass sich
diese Beschränkungen nicht auf Attribute anwenden lassen.
In XML Schema können Gruppen von Elementen definiert und benannt werden, so dass die Elemente benutzt werden können, um das Inhaltsmodell von komplexeren komplexen Typen aufzubauen (so wie in XML 1.0 die Parameter Entities). Neben Elementen in benannten Gruppen können auch unbenannte Gruppen von Elementen definiert werden. Sie können dergestalt beschränkt werden, dass sie in derselben Reihenfolge (Sequenz), in der sie deklariert wurden, auftreten müssen, oder insofern, dass in einer Instanz nur eines der Elemente auftreten darf.
Zur Verdeutlichung führen wir zwei Gruppen in die Definition des BestellungTyp
-Typs
aus dem Schema für Buchbestellungen ein, so dass Bestellungen entweder verschiedene
Liefer- und Rechnungsadressen enthalten können oder eine
einzige Adresse, falls Liefer- und Rechnungsadresse gleich sind:
<xsd:complexType name="BestellungTyp"> <xsd:sequence> <xsd:choice> <xsd:group ref="verschiedeneAdr"/> <xsd:element name="eineAdresse" type="DeAdresse"/> </xsd:choice> <xsd:element ref="Kommentar" minOccurs="0"/> <xsd:element name="Waren" type="WarenTyp"/> </xsd:sequence> <xsd:attribute name="bestelldatum" type="xsd:date"/> </xsd:complexType> <xsd:group name="verschiedeneAdr"> <xsd:sequence> <xsd:element name="Lieferadresse" type="DeAdresse"/> <xsd:element name="Rechnungsadresse" type="DeAdresse"/> </xsd:sequence> </xsd:group>
Das choice
-Element für Auswahlgruppen bewirkt, dass in einer Instanz nur eines seiner Kindelemente auftreten darf. Eines der Kindelemente
ist eine innere Gruppe (group
), welche die benannte Gruppe verschiedeneAdr
mit der Element-Sequenz Lieferadresse
, Rechnungsadresse
referenziert, und das andere Kindelement ist eineAdresse
. In einem Instanzdokument muss das Bestellung
-Element also entweder ein Lieferadresse
-Element gefolgt von einem Rechnungsadresse
-Element enthalten oder ein einzelnes eineAdresse
-Element. Auf die Auswahlgruppe (choice
) folgen die Deklarationen der Elemente Kommentar
und Waren
. Sowohl die Auswahlgruppe als auch Element-Deklarationen sind Kindelemente einer Sequenzgruppe (sequence
). Der Effekt dieser verschiedenen Gruppen ist, dass auf das bzw. die Adress-Element(e) ein Kommentar
-Element folgen kann und ein Waren
-Element folgen muss, und zwar in dieser Reihenfolge.
Es gibt noch eine dritte Möglichkeit, die Elemente in einer
Gruppe zu beschränken: Alle Elemente in der Gruppe können einmal
oder gar nicht auftreten, und zwar in beliebiger Reihenfolge.
Die all
-Gruppe
(eine vereinfachte Version des &-Konnektors von SGML) darf nur auf oberster
Ebene eines Inhaltsmodells auftreten. Außerdem dürfen als
Kinder dieser Gruppe nur einzelne Elemente auftreten, keine Gruppen, und
kein Element im Inhaltsmodell darf mehr als einmal auftreten,
d.h. die für minOccurs
und maxOccurs
gestatteten Werte sind 0 und 1. Um beispielsweise die Kindelemente von Bestellung
in beliebiger Reihenfolge auftreten zu lassen, könnte man den BestellungTyp
-Typ folgendermaßen definieren:
<xsd:complexType name="BestellungTyp"> <xsd:all> <xsd:element name="Lieferadresse" type="DeAdresse"/> <xsd:element name="Rechnungsadresse" type="DeAdresse"/> <xsd:element ref="Kommentar" minOccurs="0"/> <xsd:element name="Waren" type="WarenTyp"/> </xsd:all> <xsd:attribute name="bestelldatum" type="xsd:date"/> </xsd:complexType>
Mit dieser Definition ist ein Kommentar
-Element innerhalb von Bestellung
optional und es darf vor oder nach einem Lieferadresse
-, Rechnungsadresse
- oder Waren
-Element auftreten, jedoch insgesamt nur einmal. Außerdem erlauben die Bedingungen der all
-Gruppe es nicht, ein Element wie Kommentar
außerhalb der Gruppe zu deklarieren, um zu erreichen, dass es mehr als einmal auftreten darf. XML Schema verlangt, dass
eine all
-Gruppe als einziges Kind am Anfang eines Inhaltsmodells auftritt. Mit anderen Worten, das Folgende ist nicht erlaubt:
<xsd:complexType name="BestellungTyp"> <xsd:sequence> <xsd:all> <xsd:element name="Lieferadresse" type="DeAdresse"/> <xsd:element name="Rechnungsadresse" type="DeAdresse"/> <xsd:element name="Waren" type="WarenTyp"/> </xsd:all> <xsd:sequence> <xsd:element ref="Kommentar" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:sequence> <xsd:attribute name="bestelldatum" type="xsd:date"/> </xsd:complexType>
Benannte und unbenannte Gruppen in Inhaltsmodellen (repräsentiert durch group
bzw. choice
, sequence
und all
) können die Attribute minOccurs
und maxOccurs
tragen. Durch geeignete Kombination der verschiedenen von XML Schema angebotenen Gruppen und durch das Setzen von geeigneten
Werten für minOccurs
und maxOccurs
können alle Inhaltsmodelle, die man mit XML 1.0 DTDs ausdrücken kann, repräsentiert werden. Zusätzlich bietet die all
-Gruppe noch mehr Ausdrucksmächtigkeit.
Angenommen, wir wollen mehr Informationen zu den Büchern
in einer Bestellung hinzufügen, etwa den Autor und die Auflage. Dazu
könnte man die Attribut-Deklarationen für Auflage
und Autor
zur (anonymen) Typdefinition für Buch
hinzufügen:
<xsd:element name="Buch" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="Titel" type="xsd:string" /> <xsd:element name="Anzahl"> <xsd:simpleType> <xsd:restriction base="xsd:positiveInteger"> <xsd:maxExclusive value="100"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="PreisEUR" type="xsd:decimal"/> <xsd:element ref="Kommentar" minOccurs="0"/> <xsd:element name="Lieferdatum" type="xsd:date" minOccurs="0"/> </xsd:sequence> <xsd:attribute name="ISBN" type="ISBNTyp" use="required"/> <!-- neue Attribute --> <xsd:attribute name="Autor" type="xsd:string"/> <xsd:attribute name="Auflage"> <xsd:simpleType> <xsd:restriction base="xsd:short"> <xsd:minInclusive value="1"/> <xsd:maxInclusive value="50"/> </xsd:restriction> </xsd:simpleType> </xsd:attribute> </xsd:complexType> </xsd:element>
Alternativ dazu kann man auch eine benannte Attributgruppe erzeugen, die alle gewünschten Attribute für das Buch
-Element enthält, und diese Gruppe von der Deklaration des Buch
-Elements aus mit ihrem Namen referenzieren:
<xsd:element name="Buch" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="Titel" type="xsd:string" /> <xsd:element name="Anzahl"> <xsd:simpleType> <xsd:restriction base="xsd:positiveInteger"> <xsd:maxExclusive value="100"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="PreisEUR" type="xsd:decimal"/> <xsd:element ref="Kommentar" minOccurs="0"/> <xsd:element name="Lieferdatum" type="xsd:date" minOccurs="0"/> </xsd:sequence> <!-- Attributgruppe ersetzt einzelne Definitionen --> <xsd:attributeGroup ref="BuchAtts"/> </xsd:complexType> </xsd:element> <xsd:attributeGroup name="BuchAtts"> <xsd:attribute name="ISBN" type="ISBNTyp" use="required"/> <xsd:attribute name="Autor" type="xsd:string"/> <xsd:attribute name="Auflage"> <xsd:simpleType> <xsd:restriction base="xsd:short"> <xsd:minInclusive value="1"/> <xsd:maxInclusive value="50"/> </xsd:restriction> </xsd:simpleType> </xsd:attribute> </xsd:attributeGroup>
Durch die Verwendung von Attributgruppen kann die Lesbarkeit eines Schemas verbessert werden und außerdem erleichtert es die Wartung, da eine Attributgruppe nur an einer Stelle definiert und gewartet werden muss, aber in vielen Definitionen und Deklarationen referenziert werden kann. Diese Eigenschaften der Attributgruppe machen sie vergleichbar mit Parameter Entities in XML 1.0. Beachten Sie, dass Attributgruppen andere Attributgruppen enthalten dürfen. Beachten Sie außerdem, dass sowohl Attribut-Deklarationen als auch Referenzen auf Attributgruppen am Ende der Definition eines komplexen Typs stehen müssen.
Das erste Buch in best.xml hat kein Lieferdatum
-Element.
Im Kontext unseres Szenarios könnte der Autor des Schemas mit dem Fehlen
des Elements meinen, dass das Buch noch nicht geliefert
wurde. Im Allgemeinen hat die Abwesenheit eines Elements jedoch keine besondere
Bedeutung: Es kann heißen, dass die Information unbekannt
oder nicht anwendbar ist oder dass das Element aus irgendeinem anderen Grund
fehlt. Manchmal ist es wünschenswert, ein noch nicht geliefertes
Buch, nicht anwendbare oder unbekannte Informationen explizit
mit einem Element zu repräsentieren, nicht nur durch das Fehlen eines Elements.
Es kann zum Beispiel wünschenswert sein, einen “NULL”-Wert,
der aus einer relationalen Datenbank kommt, durch ein vorhandenes Element
zu repräsentieren. Solche Fälle können durch den Nil-Mechanismus
von XML Schema abgedeckt werden, der es ermöglicht, dass Elemente mit einem
echten Wert oder mit einem Nil-Wert auftreten.
Der Nil-Mechanismus von XML Schema funktioniert über ein
besonderes Nil-Signal: Es gibt keinen Wert Nil, der als Inhalt eines
Elements verwendet wird, sondern ein Attribut, das angibt,
dass der Wert des Elements Nil ist. Zur Verdeutlichung ändern wir
die Deklaration des Lieferdatum
-Elements, so dass Nil-Werte angegeben werden können:
<xsd:element name="Lieferdatum" type="xsd:date" nillable="true"/>
Um im Instanzdokument explizit anzugeben, dass Lieferdatum
den Wert Nil hat, setzen wir das Attribut nil
(aus dem XML Schema Namensraum für Instanzen) auf true
:
<Lieferdatum xsi:nil="true"></Lieferdatum>
Das Attribut xsi:nil
ist als Teil des XML Schema Namensraum für Instanzen, http://www.w3.org/2001/XMLSchema-instance
, definiert, also muss es im Instanzdokument mit einem Präfix (wie xsi:
), das mit diesem Namensraum assoziiert ist, erscheinen. (Wie auch beim Präfix xsd:
wird das Präfix xsi:
nur aus Konvention benutzt.) Beachten Sie, dass der Nil-Mechnismus nur für Elementwerte verwendet werden kann und nicht für
Attributwerte. Ein Element mit xsi:nil="true"
darf keinen Element-Inhalt haben, aber es darf trotzdem noch Attribute tragen.
Ein Schema kann als eine Sammlung (ein Vokabular) von Typdefinitionen
und Deklarationen von Elementen angesehen werden, deren Namen
zu einem bestimmten Namensraum gehören, dem Ziel-Namensraum. Ziel-Namensräume
erlauben uns zwischen Definitionen und Deklarationen aus verschiedenen
Vokabularen zu unterscheiden. Zum Beispiel könnte man mittels der Ziel-Namensräume
zwischen dem in der XML Schema Sprachdefinition definierten
element
und einem in einem hypothetischen Chemie-Wortschatz definierten element
unterscheiden. Das erstere gehört zum http://www.w3.org/2001/XMLSchema Ziel-Namensraum, das letztere zu einem anderen.
Um zu überprüfen, ob ein Instanzdokument einem oder mehreren Schemata entspricht (durch einen Vorgang, der Schema-Validierung heißt), müssen wir eine Zuordnung der Definitionen und Deklarationen der Attribute und Elemente zu den im Dokument benutzten Attributen und Elementen finden. Die Ziel-Namensräume spielen bei dieser Zuordnung die Hauptrolle. Im folgenden Abschnitt wird diese Rolle untersucht.
Der Autor des Schemas hat auch verschiedene Möglichkeiten zu beeinflussen, wie die Elemente und Attribute im Instanzdokument dargestellt werden. Genauer gesagt kann der Autor festlegen, wie er die Namensraumangabe für lokal deklarierte Elemente oder Attribute vornimmt. Er kann dies dies explizit mittels Präfix oder implizit durch den voreingestellten Namensraum tun. Diese Entscheidung hat eine Reihe von Auswirkungen auf die Struktur von Schemata und Instanzen, und diese Auswirkungen werden in den folgenden Abschnitten betrachtet.
In einer neuen Version unseres Schemas für Buchbestellungen, “best1.xsd”,
deklarieren wir explizit einen Namensraum und fordern, dass sowohl lokal
definierte Elemente als auch lokal definierte Attribute
nicht qualifiziert angegeben werden dürfen. Der Ziel-Namensraum von “best1.xsd” ist im Element targetNamespace
als http://www.example.com/BEST
angegeben.
Die Qualifizierung von lokalen Elementen und Attributen kann global über die beiden Attribute elementFormDefault
und attributeFormDefault
des Elements schema
bestimmt werden oder sie wird für jede einzelne Deklaration über das form
-Attribut angegeben. Jedes dieser Attribute kann die Werte qualified
oder unqualified
annehmen, um festzulegen, ob lokal definierte Elemente oder Attribute qualifiziert werden müssen oder nicht.
In “best1.xsd” bestimmen wir die Qualifizierung von Attributen und Elementen durch das Setzen von sowohl elementFormDefault
als auch attributeFormDefault
auf unqualified
. Eigentlich ist dies unnötig, da das die Standardwerte für diese Attribute sind; es sei hier zur Hervorhebung gegenüber einem
späteren Beispiel angegeben.
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:best="http://www.example.com/BEST" targetNamespace="http://www.example.com/BEST" elementFormDefault="unqualified" attributeFormDefault="unqualified"> <element name="Bestellung" type="best:BestellungTyp" /> <element name="Kommentar" type="string"/> <complexType name="BestellungTyp"> <sequence> <element name="Lieferadresse" type="best:DeAdresse"/> <element name="Rechnungsadresse" type="best:DeAdresse"/> <element ref="best:Kommentar" minOccurs="0"/> <!-- etc. --> </sequence> <attribute name="bestelldatum" type="date"/> </complexType> <complexType name="DeAdresse"> <sequence> <element name="Name" type="string"/> <element name="Straße" type="string"/> <element name="Ort" type="string"/> <element name="PLZ" type="decimal"/> </sequence> <attribute name="land" type="NMTOKEN" fixed="DE"/> </complexType> <!-- etc. --> </schema>
Wir untersuchen nun alle Typdefinitionen, um zu sehen,
wie der Ziel-Namensraum gefüllt wird. Am Ende des Schemas definieren
wir einen Typ namens DeAdresse
, der aus den Elementen Name
, Straße
usw. besteht. Dadurch, dass dieser Typ in diesem Dokument (mit dem targetNamespace
http://www.example.com/BEST
) definiert wird, wird er Teil dieses Namensraums. Des Weiteren definieren wir den Typ BestellungTyp
mit den Elementen Lieferadresse
, Rechnungsadresse
und Kommentar
. Auch dieser Typ ist Teil des Ziel-Namensraums. Zu beachten ist, dass hier die Referenzen auf den Typ DeAdresse
mit dem Präfix best:
versehen sind, welches im schema
-Tag an http://www.example.com/BEST
gebunden ist. Das Gleiche gilt für die Referenz auf Kommentar
. Dies ist derselbe Namensraum wie der Ziel-Namensraum dieses Dokuments, also wird ein bearbeitendes Programm wissen, dass
es in diesem Dokument nach der Typdefinition von DeAdresse
suchen muss. Es ist auch möglich, Typen aus anderen Dokumenten mit anderen
Ziel-Namensräumen zu adressieren, womit die Wiederverwendbarkeit
von Typdefinitionen möglich wird.
Am Anfang des Schemas “best1.xsd” deklarieren wir die Elemente Bestellung
und Kommentar
. Auch diese werden in den Ziel-Namensraum eingebunden. Der Typ von Bestellung
trägt ein Präfix, und zwar aus dem gleichen Grund, aus dem DeAdresse
mit einem Präfix versehen ist. Im Schema ist ein voreingestellter Namensraum angegeben und dadurch werden Elemente und Typen
ohne Präfix (wie string
oder element
) mit diesem Namensraum assoziiert (http://www.w3.org/2001/XMLSchema). Dies ist der Ziel-Namensraum von XML Schema selbst; also wird ein verarbeitendes Programm wissen, dass es die Definition
für den Typ string
und die Deklaration für das Element element
im Schema von XML Schema finden wird.
Jetzt werden wir betrachten, inwiefern der Ziel-Namensraum des Schemas das Instanzdokument beeinflusst:
<?xml version="1.0"?> <best:Bestellung xmlns:best="http://www..example.com/BEST" bestelldatum="1999-12-10"> <Lieferadresse land="DE"> <Name>Alice Schmid</Name> <Straße>Walnussgasse 42</Straße> <Ort>Frankfurt/Main</Ort> <PLZ>60000</PLZ> </Lieferadresse> <Rechnungsadresse land="DE"> <Name>Robert Schmid</Name> <Straße>Haselnussweg 3</Straße> <Ort>Frankfurt/Main</Ort> <PLZ>61240</PLZ> </Rechnungsadresse> <best:Kommentar>Bitte mit Geschenkverpackung!</best:Kommentar> <!-- etc. --> </best:Bestellung>
Dieses Instanzdokument deklariert genau einen Namensraum, http://www.example.com/BEST
, und verknüpft ihn mit dem Präfix best:
. Dieses Präfix wird für zwei Elemente im Dokument verwendet, und zwar für Bestellung
und Kommentar
. Der Namensraum ist derselbe wie der in “best1.xsd” angegebene Ziel-Namensraum, also wird ein bearbeitendes Programm dort die Deklarationen für Bestellung
und Kommentar
suchen und finden.
Die Benennung als Ziel-Namensraum drückt aus, dass dieser Namensraum das Ziel für die Elemente Bestellung
und Kommentar
ist. Die Ziel-Namensräume im Schema bestimmen also die
Validierung der korrespondierenden Namensräume im Instanzdokument.
Das Präfix best:
ist vor die Elemente Bestellung
und Kommentar
gesetzt. Darüber hinaus verlangen elementFormDefault
und attributeFormDefault
, dass alle lokal deklarierten Elemente (wie Lieferadresse
, Rechnungsadresse
oder Name
) kein Präfix haben, ebenso wie die Attribute, die ja alle lokal deklariert sind. Die Elemente Bestellung
und Kommentar
sind globale Elemente, da sie im Kontext des Schemas deklariert sind und nicht lokal im Kontext eines Typs. Das Element Bestellung
zum Beispiel ist im Schema ein Kind des schema
-Elements, während die Deklaration von Lieferadresse
ein Kind des complexType
-Elements ist, das BestellungTyp
definiert.
Wenn lokale Elemente
und Attribute nicht qualifiziert werden müssen, benötigt der Autor des Instanzdokuments
möglicherweise etwas mehr Wissen über das Schema, damit
er gültige Dokumente erzeugen kann. Wenn der Autor sicher sein kann, dass
nur das Wurzelelement (etwa Bestellung
) global deklariert
ist, dann muss er nur dieses qualifizieren. Andernfalls könnte der Autor
wissen, dass alle Elemente global deklariert sind, dann
müssen alle Elemente in der Instanz mit einem Präfix versehen werden. Eventuell
nutzt er dann jedoch die Vorteile eines voreingestellten
Namensraums (wie in Abschnitt 3.2
beschrieben). Wenn jedoch von keinem dieser Ansätze Gebrauch gemacht worden
ist, muss der Autor genau wissen, welche Elemente und Attribute
global deklariert sind (und qualifiziert werden müssen) und welche lokal
deklariert sind und daher kein Präfix brauchen.
Von Elementen und Attributen kann unabhängig voneinander
verlangt sein, dass sie qualifiziert angegeben werden. Wir beginnen
mit der Qualifizierung von lokalen Elementen. Um zu spezifizieren,
dass alle lokalen Elemente qualifiziert angegeben werden
müssen, setzt man den Wert von elementFormDefault
auf qualified
:
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:best="http://www.example.com/BEST" targetNamespace="http://www.example.com/BEST" elementFormDefault="qualified" attributeFormDefault="unqualified"> <element name="Bestellung" type="best:BestellungTyp" /> <element name="Kommentar" type="string"/> <complexType name="BestellungTyp"> <!-- etc. --> </complexType> <!-- etc. --> </schema>
Und im folgenden konformen Instanzdokument qualifizieren wir die Elemente explizit:
<?xml version="1.0"?> <best:Bestellung xmlns:best="http://www.example.com/BEST" bestelldatum="1999-12-10"> <best:Lieferadresse land="DE"> <best:Name>Alice Schmid</best:Name> <best:Straße>Walnussgasse 42</best:Straße> <best:Ort>Frankfurt/Main</best:Ort> <best:PLZ>60000</best:PLZ> </best:Lieferadresse> <best:Rechnungsadresse land="DE"> <best:Name>Robert Schmid</best:Name> <best:Straße>Haselnussweg 3</best:Straße> <best:PLZ>61240</best:PLZ> <best:Ort>Frankfurt/Main</best:Ort> </best:Rechnungsadresse> <best:Kommentar>Bitte mit Geschenkverpackung!</best:Kommentar> <!-- etc. --> </best:Bestellung>
Als Alternative bietet sich an, anstatt jedes Element explizit zu qualifizieren, diese Qualifizierung implizit durch einen voreingestellten Namensraum vorzunehmen:
<?xml version="1.0"?> <Bestellung xmlns="http://www.example.com/BEST" bestelldatum="1999-12-10"> <Lieferadresse land="DE"> <Name>Alice Schmid</Name> <Straße>Walnussgasse 42</Straße> <Ort>Frankfurt/Main</Ort> <PLZ>60000</PLZ> </Lieferadresse> <Rechnungsadresse land="DE"> <Name>Robert Schmid</Name> <Straße>Haselnussweg 3</Straße> <Ort>Frankfurt/Main</Ort> <PLZ>61240</PLZ> </Rechnungsadresse> <Kommentar>Bitte mit Geschenkverpackung!</Kommentar> <!-- etc. --> </Bestellung>
In “best2.xml” gehören alle Elemente zum gleichen Namensraum. Das xmlns
-Attribut
deklariert einen voreingestellten Namensraum, der damit zu allen Elementen
des Dokuments gehört. Dadurch ist es nicht mehr nötig,
ein Präfix vor die Elemente zu setzen. Weitere Beispiele für die Verwendung
von qualifizierten Elementen sind in Kapitel 5 zu finden; dort fordern die Schemata, dass alle Elemente qualifiziert sind.
Die Qualifizierung von Attributen ist der Qualifizierung von Elementen sehr ähnlich. Wenn das attributeFormDefault
-Attribut auf qualified
gesetzt oder wenn ein Attribut global deklariert ist, muss es im Instanzdokument mit einem Präfix versehen werden. Ein Beispiel
für ein qualifiziertes Attribut ist das Attribut xsi:nil
, welches in Abschnitt 2.9 vorgestellt wurde. Anders als Elemente müssen Attribute, die qualifiziert werden müssen, ein Präfix tragen, weil XML-Namespaces
keinen voreingestellten Namensraum für Attribute vorsehen. Attribute, die
nicht qualifiziert sein müssen, erscheinen im Dokument
ohne Präfix, was der Normalfall ist.
Der Qualifizierungsmechanismus, den wir bisher betrachtet
haben, kontrolliert alle lokalen Elemente und Attribute innerhalb
eines bestimmten Ziel-Namensraums. Es ist aber auch möglich, die
Qualifizierung einer einzelnen Deklaration über das Attribut
form
zu steuern. Um zum Beispiel zu fordern, dass ein lokal deklariertes Attribut publicKey
in Dokumenten qualifiziert angegeben wird, deklarieren wir es wie folgt:
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:best="http://www.example.com/BEST" targetNamespace="http://www.example.com/BEST" elementFormDefault="qualified" attributeFormDefault="unqualified"> <!-- etc. --> <element name="Sicherheit"> <complexType> <sequence> <!-- Elementdeklarationen --> </sequence> <attribute name="publicKey" type="base64Binary" form="qualified"/> </complexType> </element> </schema>
Beachten Sie, dass das Attribut form
den Wert von attributeFormDefault
nur für das Attribut publicKey
überschreibt. Das Attribut form
kann auf die gleiche Weise bei Elementen angewendet werden. Das folgende Dokument entspricht dem neuen Schema:
<?xml version="1.0"?> <Bestellung xmlns="http://www.example.com/BEST" xmlns:best="http://www.example.com/BEST" bestelldatum="1999-12-10"> <!-- etc. --> <Sicherheit best:publicKey="GpM7"> <!-- etc. --> </Sicherheit> <Bestellung>
Eine weitere Möglichkeit für den Autor eines Schemas bietet
sich an, wenn die Namen aller Elemente in einem Namensraum einzigartig
sind. Er kann dann alle Elemente global deklarieren, was
den gleichen Effekt wie der Gebrauch von ELEMENT
in einer DTD hat. Im folgenden Beispiel haben wir das Schema best1.xsd so verändert, dass alle Elemente global deklariert sind. Wir haben in diesem Beispiel die Attribute elementFormDefault
und attributeFormDefault
weggelassen, um zu betonen, dass ihre Werte irrelevant sind, wenn es nur globale Elemente und Attribute gibt.
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:best="http://www.example.com/BEST" targetNamespace="http://www.example.com/BEST"> <element name="Bestellung" type="best:BestellungTyp" /> <element name="Lieferadresse" type="best:DeAdresse"/> <element name="Rechnungsadresse" type="best:DeAdresse"/> <element name="Kommentar" type="string"/> <element name="Name" type="string"/> <element name="Straße" type="string"/> <complexType name="BestellungTyp"> <sequence> <element ref="best:Lieferadresse" minOccurs="0"/> <element ref="best:Rechnungsadresse" minOccurs="0"/> <element ref="best:Kommentar" minOccurs="0"/> <!-- etc. --> </sequence> <attribute name="bestelldatum" type="date"/> </complexType> <complexType name="DeAdresse"> <sequence> <element ref="best:Name"/> <element ref="best:Straße"/> <!-- etc. --> </sequence> <attribute name="land" type="NMTOKEN" fixed="DE"/> </complexType> <!-- etc. --> </schema>
Diese "globale" Version von “best1.xsd” validiert das Instanzdokument “best2.xml”, welches wie gesagt auch gegen die "qualifizierte" Version von Schema “best1.xsd”
gültig ist. Mit anderen Worten, beide Ansätze für das Schema validieren dasselbe
mit einem voreingestellten Namensraum versehene Instanzdokument.
Somit sind sie in einem Aspekt sehr ähnlich, in einem anderen, wichtigen
Sinne sind sie jedoch sehr verschieden. Wenn alle Elemente
global deklariert sind, ist es insbesondere nicht möglich, die Vorteile von
lokalen Namen zu nutzen. Betrachten wir zum Beispiel ein
Schema für Bücher, in dem man sowohl den Titel des Buches als auch Informationen
über den Autor spezifizieren will. Verwendet man nur globale
Deklarationen, kann man nur ein Element Titel
deklarieren. Mit lokalen Deklarationen kann man ein Subelement eines Elements Buch
, und im gleichen Schema ein Subelement für Autor
anlegen, das auch Titel
heißt und den Titel des Autors beinhaltet, also zum Beispiel "Dr." oder "Prof. Dr.".
In Kapitel 2 haben wir die Grundlagen von Schemata anhand eines Schemas erklärt, das keinen Ziel-Namensraum hatte, und anhand eines Instanzdokuments, das keinen Namensraum deklarierte. Es stellt sich die Frage: Was ist in diesen Beispielen der Ziel-Namensraum und wie wird er referenziert?
In dem Schema für Bestellungen, “best.xsd”,
haben wir weder einen Ziel-Namensraum noch ein Präfix deklariert, das mit
diesem Ziel-Namensraum assoziiert wäre, um die Typen und
Elemente, die in diesem Schema definiert sind, zu referenzieren. Die Konsequenz
daraus ist, dass alle Elemente dieses Schemas, wie BestellungTyp
oder DeAdresse
, ohne Qualifizierung des Namensraums benutzt werden müssen. Es gibt dann weder ein explizites Namensraum-Präfix, noch wird
der Namensraum implizit angegeben. So wird zum Beispiel das Element Bestellung
mit dem Typ BestellungTyp
angegeben. Im Gegensatz dazu werden alle XML Schema Elemente, die in “best.xsd” verwendet werden, mit dem Präfix xsd:
qualifiziert, das mit dem XML Schema Namensraum verknüpft ist.
In Fällen, in denen ein Schema ohne Ziel-Namensraum erstellt
wird, wird dringend empfohlen, alle XML Schema Elemente und Typen
explizit mit einem Präfix wie xsd:
zu versehen, das mit dem XML Schema Namensraum verknüpft ist (wie in “best.xsd”
geschehen). Der Grund für diese Empfehlung ist, dass in XML Schema Elemente
und Typen, wenn sie unqualifiziert angegeben sind automatisch
dem Namensraum von XML-Schema zugeordnet werden und daher nicht mehr von
Referenzen auf selbst definierte Typen zu unterscheiden
sind.
Element-Deklarationen aus einem Schema ohne Ziel-Namensraum validieren
nicht-qualifizierte Elemente in einem Instanzdokument.
Das bedeutet, sie validieren Elemente, für die weder explizit per Präfix
noch implizit durch ein xmlns:
-Attribut
ein Namensraum angegeben ist. Also muss man ein Schema ohne Ziel-Namensraum
verwenden, wenn man ein XML 1.0 Dokument validieren will,
das keine Namensräume benutzt. Natürlich gibt es noch viele XML 1.0 Dokumente,
die keine Namensräume verwenden (weil sie noch aus der
Zeit stammen, als es Namensräume in XML noch nicht gab), also wird es viele
XML Schemata ohne Ziel-Namensraum geben. Es muss darauf
geachtet werden, dem Schema-Prozessor für die Validierung ein Schema-Dokument
zu geben, das zum verwendeten Vokabular passt.
Das Schema für Bestellungen, das wir in Kapitel 2 als Beispiel verwendet haben, bestand aus einer einzigen Datei und die meisten Schema-Konstrukte (Element-Deklarationen oder Typdefinitionen) waren komplett neu geschrieben. Im wirklichen Leben jedoch werden Schema-Autoren ihre Schemata aus schon bestehenden Schemata in unterschiedlichen Dateien zusammensetzen und Typen basierend auf anderen Typen erstellen wollen. In diesem Kapitel untersuchen wir die Mechanismen, die solche Kompositionen ermöglichen.
Wenn Schemata größer werden, ist es wünschenswert, ihren Inhalt auf mehrere Dateien aufzuteilen. Dadurch werden die Wartung, die Zugriffsregelung und auch die Lesbarkeit des Schemas verbessert. Um dies zu illustrieren, entfernen wir die Konstrukte, die mit Adressen zu tun haben, aus dem Schema “best.xsd” und gliedern sie in eine neue Datei, “adresse.xsd”, aus. Das geänderte Bestellungs-Schema nennen wir “ibest.xsd”.
<schema targetNamespace="http://www.example.com/IBEST" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:ibest="http://www.example.com/IBEST"> <annotation> <documentation xml:lang="DE"> Internationales Buchbestellungsschema für Example.com. Copyright 2001 Example.com. Alle Rechte vorbehalten. </documentation> </annotation> <!-- Einbinden der Adress-Konstrukte --> <include schemaLocation="http://www.example.com/schemas/adresse.xsd"/> <element name="Bestellung" type="BestellungTyp" /> <element name="Kommentar" type="string"/> <complexType name="BestellungTyp"> <sequence> <element name="Lieferadresse" type="DeAdresse"/> <element name="Rechnungsadresse" type="DeAdresse"/> <element ref="Kommentar" minOccurs="0"/> <element name="Waren" type="ibest:WarenTyp"/> </sequence> <attribute name="bestelldatum" type="date"/> </complexType> <complexType name="WarenTyp"> <sequence> <element name="Buch" minOccurs="0" maxOccurs="unbounded"> <complexType> <sequence> <element name="Titel" type="string" /> <element name="Anzahl"> <simpleType> <restriction base="positiveInteger"> <maxExclusive value="100"/> </restriction> </simpleType> </element> <element name="PreisEUR" type="decimal"/> <element ref="Kommentar" minOccurs="0"/> <element name="Lieferdatum" type="date" minOccurs="0"/> </sequence> <attribute name="ISBN" type="ISBNTyp" use="required"/> </complexType> </element> </sequence> </complexType> <simpleType name="ISBNTyp"> <restriction base="string"> <pattern value="\d{9}[0-9X]"/> <!-- 9 Ziffern gefolgt von einer Prüfziffer im Bereich zwischen 0 und 10, 10 wird als X dargestellt --> </restriction> </simpleType> </schema>
Die Konstrukte für Adressen werden in folgender Datei definiert:
<schema targetNamespace="http://www.example.com/IBEST" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:ibest="http://www.example.com/IBEST"> <annotation> <documentation xml:lang="DE"> Adressen für das internationale Buchbestellungsschema für Example.com. Copyright 2001 Example.com. Alle Rechte vorbehalten. </documentation> </annotation> <complexType name="Adresse"> <sequence> <element name="Name" type="string"/> <element name="Straße" type="string"/> <element name="Ort" type="string"/> </sequence> </complexType> <complexType name="DeAdresse"> <complexContent> <extension base="ibest:Adresse"> <sequence> <element name="PLZ" type="decimal"/> </sequence> </extension> </complexContent> </complexType> <complexType name="USAAdresse"> <complexContent> <extension base="ibest:Adresse"> <sequence> <element name="Bundesstaat" type="ibest:USBundesStaat"/> <element name="PLZ" type="positiveInteger"/> </sequence> <attribute name="exportCode" type="positiveInteger" fixed="1"/> </extension> </complexContent> </complexType> <simpleType name="USBundesStaat"> <restriction base="string"> <enumeration value="AK"/> <enumeration value="AL"/> <enumeration value="AR"/> <!-- etc. --> </restriction> </simpleType> </schema>
Die verschiedenen Konstrukte für Buchbestellungen und Adressen sind jetzt auf zwei Dateien verteilt, “ibest.xsd” und “adresse.xsd”. Um diese Konstrukte in das Schema für internationale Buchbestellungen zu integrieren, oder besser gesagt, um sie in diesen
Namensraum einzubinden, beinhaltet “ibest.xsd” ein include
-Element:
<include schemaLocation="http://www.example.com/schemas/adresse.xsd"/>
Dieses include
-Element holt die Deklarationen und Definitionen aus “adresse.xsd” und macht sie im Namensraum für internationale Buchbestellungen verfügbar. Der wichtige Vorbehalt beim Verwenden des include
-Elements ist, dass das eingebundene Schema denselben Ziel-Namensraum haben muss wie das einbindende Schema, in diesem Fall
http://www.example.com/IBEST
. In Abschnitt 4.5 beschreiben wir einen ähnlichen Mechanismus, der es erlaubt, bestimmte Elemente während des Einbindens zu ändern.
In unserem Beispiel gibt es nur ein einbindendes und ein
eingebundenes Dokument. In der Praxis ist es möglich, mehrere Dokumente
mit mehreren include
-Elementen einzubinden, und man kann Dokumente einbinden, die wiederum andere einbinden. Man muss jedoch beachten, dass alle
Dokumente einer solchen Kette denselben Ziel-Namensraum haben müssen.
Instanzdokumente, die zu einem Schema konform sind, das
über mehrere Dokumente verteilt ist, brauchen nur das “oberste” Dokument
und den allgemeinen Namensraum zu adressieren. Es liegt
in der Verantwortung des Prozessors, die Definitionen aus den verschiedenen
Dokumenten zusammenzusammeln. In unserem oben angeführten
Beispiel referenziert das Instanzdokument “ibest.xml” (siehe Abschnitt 4.3) nur den gemeinsamen Ziel-Namensraum http://www.example.com/IBEST
und (implizit) das Schema http://www.example.com/schemas/ibest.xsd
. Der Prozessor muss die Datei “adresse.xsd” selbst finden.
In Abschnitt 5.4 beschreiben wir, wie Schemata Inhalte aus mehreren Namensräumen validieren können.
Um unsere Adress-Konstrukte zu erstellen, fangen wir wie gewohnt mit einem komplexen Typ namens Adresse
an (siehe “adresse.xsd”). Der Typ Adresse
beinhaltet die grundlegenden Elemente einer Adresse: einen Namen, eine Straße
und eine Stadt. (Diese Definition wird eventuell nicht
für alle Länder funktionieren, aber für dieses Beispiel soll sie genügen.)
Von diesem Startpunkt aus leiten wir zwei neue komplexe
Typen ab, welche die Elemente des Originals beinhalten und zusätzlich einige
Elemente, die für Adressen in Deutschland oder in den USA
spezifisch sind. Die hier benutzte Technik, neue komplexe Typen durch Ableitung
eines bestehenden Typs zu erstellen, ist die gleiche, wie
sie schon in Abschnitt 2.5.1 vorgestellt worden ist, nur dass die Basis hier ein komplexer Typ ist, während es vorher ein einfacher Typ war.
Es werden mittels des complexType
-Elements zwei neue Typen definiert, DeAdresse
und USAAdresse
. Zusätzlich wird durch die Benutzung des Elements complexContent
signalisiert, dass auch der Inhalt der Erweiterung komplex ist, also Elemente beinhaltet, und durch den Wert des base
-Attributs des extension
-Elements wird angezeigt, dass wir den Typ Adresse
erweitern.
Wenn ein komplexer Typ durch Erweiterung abgeleitet wird,
dann ist sein effektives Inhaltsmodell das des Basistyps, ergänzt
durch das Inhaltsmodell, welches in der Ableitung angegeben ist.
Darüber hinaus werden die beiden Inhaltsmodelle so behandelt,
als seien sie Kindelemente einer Sequenzgruppe. Im Fall von USAAdresse
besteht das Inhaltsmodell aus dem Inhaltsmodell von Adresse
plus den Deklarationen für Bundesstaat
und PLZ
sowie für das Attribut exportCode
. Eine nicht zusammengesetzte Deklaration von USAAdresse
sähe so aus:
<complexType name="USAAdresse"> <sequence> <!-- Inhaltsmodell aus "Adresse" --> <element name="Name" type="string"/> <element name="Straße" type="string"/> <element name="Ort" type="string"/> <!-- erweiterte Elementdeklaration --> <element name="Bundesstaat" type="ibest:USBundesStaat"/> <element name="PLZ" type="positiveInteger"/> </sequence> <!-- angehängte Attributdeklaration --> <attribute name="exportCode" type="positiveInteger" fixed="1"/> </complexType>
In unserem Beispielszenario werden Bestellungen als Reaktion
auf Kundenbestellungen generiert, welche Liefer- und Rechnungsadressen
in verschiedenen Ländern beinhalten können. Eine internationale
Bestellung, “ibest.xml”,
zeigt einen solchen Fall, in dem die Rechnungsadresse in Deutschland ist,
die Bücher jedoch in die USA geschickt werden sollen. Offensichtlich
ist es besser, wenn das Schema für internationale Buchbestellungen nicht
jede erdenkliche Möglichkeit an Kombinationen von internationalen
Adressen fest verdrahtet anbieten muss. Ein noch größerer Vorteil ist, dass
wir sehr leicht weitere komplexe Typen für internationale
Adressen von Adresse
ableiten können.
XML Schema erlaubt es, die Elemente Lieferadresse
und Rechnungsadresse
mit dem Typ Adresse
zu definieren (siehe “ibest.xsd”), aber in Instanzdokumenten Instanzen von internationalen Adressen anstelle von Adresse
zu benutzen. Mit anderen Worten, ein Instanzdokument, dessen Inhalt dem Typ USAAdresse
entspricht, ist auch dann gültig, wenn dieser Inhalt an einer Stelle im Dokument erscheint, an der eine Adresse
erwartet wird. Damit dies funktioniert und damit genau definiert ist, welcher abgeleitete Typ gemeint ist, muss dieser im
Instanzdokument angegeben sein. Der Typ wird durch das Attribut xsi:type
angezeigt, das Teil des XML Schema Instanz-Namensraums ist. Im Beispiel “ibest.xml” wird der Gebrauch der abgeleiteten Typen DeAdresse
und USAAdresse
durch die Werte der Attribute xsi:type
angezeigt.
<?xml version="1.0"?> <ibest:Bestellung xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ibest="http://www.example.com/IBEST" bestelldatum="1999-12-10"> <Lieferadresse exportCode="1" xsi:type="ibest:USAAdresse"> <Name>Alice Smith</Name> <Straße>42 Walnut Alley</Straße> <Ort>Old Town</Ort> <Bundesstaat>PA</Bundesstaat> <PLZ>95819</PLZ> </Lieferadresse> <Rechnungsadresse xsi:type="ibest:DeAdresse"> <Name>Robert Schmid</Name> <Straße>Haselnussweg 3</Straße> <Ort>Frankfurt/Main</Ort> <PLZ>61240</PLZ> </Rechnungsadresse> <ibest:Kommentar>Bitte mit original deutscher Geschenkverpackung!</ibest:Kommentar> <Waren> <Buch ISBN="3776622148"> <Titel>Vom Glück der Faulheit. Lebensenergie richtig einteilen.</Titel> <Anzahl>1</Anzahl> <PreisEUR>29.90</PreisEUR> </Buch> <!-- etc. --> </Waren> </ibest:Bestellung>
In Abschnitt 4.8 wird erklärt, wie man verhindert, dass abgeleitete Typen auf diese Weise benutzt werden können.
Zusätzlich zu der Möglichkeit, neue komplexe Typen durch Erweiterung der Inhaltsmodelle abzuleiten, kann man neue Typen auch durch eine Einschränkung des Inhaltsmodells der bestehenden Typen erhalten. Konzeptionell ist die Einschränkung von komplexen Typen das selbe wie die Einschränkung von einfachen Typen, allerdings braucht man bei komplexen Typen eine Typdeklaration und nicht nur eine Angabe des zulässigen Wertebereichs. Ein durch Einschränkung abgeleiteter komplexer Typ ist seinem Basistyp sehr ähnlich, nur dass die Deklaration etwas einschränkender ist als die Deklaration des Basistyps. Die Menge der durch den neuen Typ repräsentierten Werte ist in der Tat eine Untermenge der durch den Basistyp beschriebenen Werte (wie auch im Falle der Einschränkung eines einfachen Typs). Mit anderen Worten: Eine Anwendung, die auf die Werte des Basistyps vorbereitet ist, wäre auch von den Werten des abgeleiteten Typs nicht überrascht.
Als Beispiel wollen wir unsere Definition einer Buchbestellung so ändern,
dass in der Liste der Bücher immer mindestens ein Buch
enthalten sein muss; das Schema “ibest.xsd” erlaubt es, dass ein WarenTyp
-Element ganz ohne Kindelemente auftreten kann. Um den neuen Typ BestätigteWarenTyp
zu erstellen, deklarieren wir ihn wie gewohnt, legen fest, dass er vom Typ WarenTyp
abgeleitet ist, und geben einen etwas einschränkenderen Wert für das minimale Vorkommen der Buch
-Elemente an. Alle Komponenten des Basistyps, die im abgeleiteten Typ enthalten sein sollen, müssen aufgeführt werden:
BestätigteWarenTyp
als Ableitung von WarenTyp
durch Einschränkung
<complexType name="BestätigteWarenTyp"> <complexContent> <restriction base="ibest:WarenTyp"> <sequence> <!-- Das Element "Buch" wird geändert --> <element name="Buch" minOccurs="1" maxOccurs="unbounded"> <!-- Der Rest der Deklaration bleibt gleich --> <complexType> <sequence> <element name="Titel" type="string"/> <element name="Anzahl"> <simpleType> <restriction base="positiveInteger"> <maxExclusive value="100"/> </restriction> </simpleType> </element> <element name="PreisEUR" type="decimal"/> <element ref="ibest:Kommentar" minOccurs="0"/> <element name="Lieferdatum" type="date" minOccurs="0"/> </sequence> <attribute name="ISBN" type="ibest:ISBNTyp" use="required"/> </complexType> </element> </sequence> </restriction> </complexContent> </complexType>
Anstatt null oder mehr Kindelementen
muss es jetzt mindestens ein Kindelement geben. Diese Änderung schränkt die
erlaubte Anzahl der Kindelemente weiter ein, indem das
Minimum für die Anzahl der vorkommenden Kindelemente von 0 auf 1 angehoben
wird. Alle BestätigteWarenTyp
-Elemente werden auch als WarenTyp
-Elemente akzeptiert.
Um die in XML Schema möglichen Einschränkungen von Typen weiter zu illustrieren, zeigt Tabelle 3 einige Beispiele, wie Element- und Attributdeklarationen in Typdeklarationen eingeschränkt werden dürfen (die Tabelle zeigt die Syntax für Elemente, obwohl die ersten drei Beispiele auch gültige Attribut-Einschränkungen sind).
Tabelle 3: Beispiele für Einschränkungen | ||
---|---|---|
Basis | Einschränkung | Bemerkung |
- | default="1" | Einen Vorgabe-Wert setzen, wo vorher keiner definiert war |
- | fixed="100" | Einen festen Wert setzen, wo vorher keiner definiert war |
- | type="string" | Einen Typ spezifizieren, wo vorher keiner angegeben war |
(minOccurs, maxOccurs) | (minOccurs, maxOccurs) | - |
(0, 1) | (0, 0) | Ausschließen eines optionalen Teils; dies kann auch erreicht werden, indem die Deklaration ausgelassen wird |
(0, unbounded) | (0, 0) (0, 37) | - |
(1, 9) | (1, 8) (2, 9) (4, 7) (3, 3) | - |
(1, unbounded) | (1, 12) (3, unbounded) (6, 6) | - |
(1, 1) | - | Weder minOccurs noch maxOccurs können in diesem Fall eingeschränkt werden.
|
In Kapitel 4.1
haben wir beschrieben, wie man Definitionen und Deklarationen aus externen
Schema-Dateien mit demselben Ziel-Namensraum einbindet.
Der include
Mechanismus erlaubt es, extern erzeugte Schemakomponenten so wie sie sind zu verwenden, also ohne Modifikationen. Wir haben
eben beschrieben, wie man neue Typen durch Erweiterung und durch Einschränkung ableitet. Der redefine
-Mechanismus,
den wir hier beschreiben, ermöglicht es, einfache und komplexe Typen, Gruppen
und Attributgruppen, die aus externen Schema-Dateien kommen,
umzudefinieren. Wie beim include
-Mechanismus müssen beim redefine
-Mechanismus
die externen Komponenten im selben Ziel-Namensraum wie das umdefinierende
Schema sein, obwohl auch externe Komponenten aus Schemata,
die keinen Namensraum haben, umdefiniert werden können. Im letzteren Fall
werden die umdefinierten Komponenten Teil des Namensraums
des umdefinierenden Schemas.
Um den redefine
-Mechanismus zu veranschaulichen, benutzen wir ihn anstelle von include
, um im Schema der internationalen Buchbestellung, ibest.xml, die Definition des komplexen Typs Adresse
, der in adresse.xml enthalten ist, zu modifizieren:
redefine
in der internationalen Buchbestellung
<schema targetNamespace="http://www.example.com/IBEST" xmlns="http://www.w3.org/2001/XMLSchema"> xmlns:ibest="http://www.example.com/IBEST"> <!-- Einbinden der Adress-Konstrukte --> <redefine schemaLocation="http://www.example.com/schemas/adresse.xsd"> <!-- Umdefinieren von Adresse --> <complexType name="Adresse"> <complexContent> <extension base="ibest:Adresse"> <sequence> <element name="Land" type="string"/> </sequence> </extension> </complexContent> </complexType> </redefine> <!-- usw. --> </schema>
Das redefine
-Element verhält sich ganz ähnlich wie das include
-Element, indem es alle Deklarationen und Definitionen aus der Datei adresse.xsd einfügt. Die Typdefinition des komplexen Typs Adresse
verwendet die bekannte Erweiterungssyntax, um das Land
-Element zur Definition von Adresse
hinzuzufügen. Beachten Sie jedoch, dass der Basistyp ebenfalls Adresse
ist. Außerhalb des redefine
-Elements
würde so ein Versuch, einen komplexen Typ mit demselben Namen (und im selben
Namensraum) wie der Basistyp, von dem er abgeleitet ist,
zu definieren, zu einem Fehler führen. In diesem Fall gibt es jedoch keinen
Fehler und die erweiterte Definition von Adresse
wird zur einzigen Definition von Adresse
.
Nachdem Adresse
umdefiniert ist, gilt die Erweiterung für alle Schemakomponenten, die Adresse
verwenden. Beispielsweise enthält adresse.xsd Definitionen für internationale Adress-Typen, die von Adresse
abgeleitet sind. Diese Ableitungen spiegeln den umdefinierten Adresse
-Typ wider, wie im folgenden Codefragment gezeigt wird:
.... <Lieferadresse exportCode="1" xsi:type="ibest:USAAdresse"> <Name>Robert Smith</Name> <Straße>8 Oak Avenue</Straße> <Ort>Old Town</Ort> <!-- Land wurde zum Basistyp Adresse von USAAdresse hinzugefügt --> <Land>USA</Land> <!-- Bundesstaat und PLZ wurden von USAAdresse hinzugefügt --> <Bundesstaat>PA</Bundesstaat> <PLZ>95819</PLZ> </Lieferadresse> ...
In unserem Beispiel wurde viel Sorgfalt darauf verwandt sicherzustellen, dass der umdefinierte Adresse
-Typ keine Konflikte mit den Typen verursacht, die von der Original-Definition von Adresse
abgeleitet wurden. Beachten Sie jedoch, dass es sehr einfach wäre, einen Konflikt zu erzeugen. Wenn die Definitionen der
abgeleiteten Typen für internationale Adressen beispielsweise Adresse
um ein Land
-Element erweitert hätten, dann würde die Redefinition von Adresse
ein Element mit demselben Namen zum Inhaltsmodell von Adresse
hinzufügen. Es ist unzulässig, in einem Inhaltsmodell zwei Elemente mit demselben Namen (und im selben Ziel-Namensraum),
aber unterschiedlichen Typen zu haben, deshalb würde der Versuch, Adresse
umzudefinieren, zu einem Fehler führen. Allgemein schützt redefine
nicht vor solchen Fehlern und sollte daher mit Vorsicht verwendet werden.
XML Schema bietet einen Mechanismus, genannt Ersetzungsgruppen,
der es erlaubt, Elemente durch andere Elemente zu ersetzen.
Genauer gesagt, Elemente können einer speziellen Gruppe von Elementen
zugeordnet werden, die für ein bestimmtes benanntes Element,
genannt Ursprungs-Element, als ersetzbar gelten. (Beachten Sie, dass das
Ursprungs-Element als globales Element deklariert sein
muss.) Zur Veranschaulichung deklarieren wir zwei Elemente namens KundenKommentar
und LieferKommentar
und ordnen sie einer Ersetzungsgruppe mit dem Ursprungs-Element Kommentar
zu, so dass KundenKommentar
und LieferKommentar
überall dort eingesetzt werden können, wo auch Kommentar
verwendet werden kann. Elemente in einer Ersetzungsgruppe müssen denselben
Typ haben wie das Ursprungs-Element; alternativ können
sie einen Typ haben, der vom Typ des Ursprungs-Elements abgeleitet ist. Um
die beiden neuen Elemente zu deklarieren und sie für das
Kommentar
-Element ersetzbar zu machen, verwenden wir die folgende Syntax:
<element name="LieferKommentar" type="string" substitutionGroup="ibest:Kommentar"/> <element name="KundenKommentar" type="string" substitutionGroup="ibest:Kommentar"/>
Wenn diese Deklarationen zum Schema der internationalen Buchbestellung hinzugefügt werden, können KundenKommentar
und LieferKommentar
im Instanzdokument für Kommentar
substituiert werden, wie folgendes Beispiel zeigt:
<Waren> <Buch ISBN="3548359698"> <Titel>Warum Männer nicht zuhören und Frauen schlecht einparken.</Titel> <Anzahl>1</Anzahl> <PreisEUR>8.95</PreisEUR> <ibest:LieferKommentar>Falls möglich mit gold-farbenem Geschenkpapier.</ibest:LieferKommentar> <ibest:KundenKommentar>Unbedingt bis Weihnachten liefern!</ibest:KundenKommentar> <Lieferdatum>2001-12-05</Lieferdatum> </Buch> </Waren>
Beachten Sie, dass es bei Element-Ersetzungen, deren Typen
vom Typ des Ursprungs-Elements abgeleitet sind, im Instanzdokument
nicht nötig ist, den abgeleiteten Typ durch ein xsi:type
-Konstrukt zu kennzeichnen, wie wir es in Kapitel 4.3 beschrieben haben.
Die Existenz einer Ersetzungsgruppe erfordert weder, dass irgendwelche Elemente aus dieser Klasse benutzt werden, noch schließt sie die Verwendung des Ursprungs-Elements aus. Ersetzungsgruppen schaffen lediglich die Möglichkeit, zu erlauben, dass Elemente untereinander austauschbar benutzt werden.
XML Schema bietet einen Mechanismus, um die Ersetzung eines
bestimmten Elements oder Typs zu erzwingen. Wenn ein Element oder
Typ als “abstract
” deklariert wird, kann
es in einem Instanzdokument nicht benutzt werden. Wenn ein Element abstrakt
deklariert ist, muss im Instanzdokument ein Element aus
der Ersetzungsgruppe dieses Elements erscheinen. Wenn die zu einem Element
korrespondierende Typdefinition abstrakt deklariert ist,
müssen alle Instanzen dieses Elements das xsi:type
-Attribut verwenden, um einen abgeleiteten Typ anzugeben, der nicht abstrakt ist.
Im Ersetzungsgruppen-Beispiel aus Abschnitt 4.6 wäre es sinnvoll, die Verwendung des Kommentar
-Elements ausdrücklich zu verbieten, so dass Instanzen das LieferKommentar
- oder das KundenKommentar
-Element verwenden müssen. Um das Kommentar
-Element abstrakt zu machen, modifizieren wir die ursprüngliche Deklaration im Schema der internationalen Buchbestellung,
ibest.xsd, wie folgt:
<element name="Kommentar" type="string" abstract="true"/>
Mit der Definition von Kommentar
als abstrakt sind Instanzen von internationalen Buchbestellungen nur gültig, wenn sie anstelle von Kommentar
die Elemente KundenKommentar
oder LieferKommentar
enthalten.
Die Deklaration eines Elements als abstrakt erfordert die
Verwendung einer Ersetzungsgruppe. Die Deklaration eines Typs als
abstrakt erfordert einfach die Verwendung eines abgeleiteten (und
durch das xsi:type
-Attribut gekennzeichneten) Typs im Instanzdokument.
Betrachten Sie die folgende Schema-Definition:
<schema xmlsns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://autos.example.com/schema" xmlns:ziel="http://autos.example.com/schema"> <complexType name="Fahrzeug" abstract="true"/> <complexType name="Auto"> <complexContent> <extension base="ziel:Fahrzeug"/> </complexContent> </complexType> <complexType name="Flugzeug"> <complexContent> <extension base="ziel:Fahrzeug"/> </complexContent> </complexType> <element name="Transportmittel" type="ziel:Fahrzeug"/> </schema>
Das Transportmittel
-Element ist nicht abstrakt, also kann es in Instanzdokumenten auftreten. Weil jedoch seine Typdefinition abstrakt ist, kann
es nie in einem Instanzdokument auftreten, ohne dass ein xsi:type
-Attribut auf einen abgeleiteten Typ verweist. Das bedeutet, dass Folgendes nicht schema-gültig ist:
<Transportmittel xmlns="http://autos.example.com/schema"/>
Der Typ des Transportmittel
-Elements ist nämlich abstrakt. Folgendes jedoch ist schema-gültig:
<Transportmittel xmlns="http://autos.example.com/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Auto"/>
weil es einen nicht-abstrakten Typ benutzt, der für Fahrzeug
substituierbar ist.
Bis jetzt konnten wir neue Typen ableiten und sie in Instanzdokumenten ohne Einschränkungen verwenden. In der Realität werden Schema-Autoren manchmal mehr Kontrolle über Ableitungen von bestimmten Typen und über die Verwendung von abgeleiteten Typen in Instanzen wünschen.
XML Schema bietet einige Mechanismen, um die Ableitung von Typen zu
steuern. Einer dieser Mechanismen erlaubt es Schema-Autoren,
für einen bestimmten komplexen Typ festzulegen, dass von ihm keine
neuen Typen abgeleitet werden dürfen, entweder (a) nicht
durch Erweiterung, (b) nicht durch Einschränkung, oder (c) überhaupt nicht.
Zur Veranschaulichung nehmen wir an, wir wollten jede Ableitung
des Adresse
-Typs durch Einschränkung verhindern, weil wir ihn nur als Basis für erweiterte Typen, wie USAAdresse
, verwenden möchten. Um solche Ableitungen zu verhindern, ändern wir die ursprüngliche Definition von Adresse
geringfügig ab, wie im Folgenden:
Adresse
durch Einschränkung verhindern
<complexType name="Adresse" final="restriction"> <sequence> <element name="Name" type="string"/> <element name="Straße" type="string"/> <element name="Ort" type="string"/> </sequence> </complexType>
Der Wert restriction
für das final
-Attribut verhindert Ableitung durch Einschränkung. Um jede Art von Ableitung oder Ableitung durch Erweiterung zu verhindern,
benutzt man die Attributwerte #all
bzw. extension
. Außerdem gibt es ein optionales finalDefault
-Attribut auf dem schema
-Element, dessen Wert einer der für das final
-Attribut erlaubten Werte sein kann. Mit der Spezifikation eines finalDefault
-Attributs kann derselbe Effekt erreicht werden wie mit der Spezifikation eines final
-Attributs auf jeder Typdefinition und Element-Deklaration im Schema.
Ein anderer Mechanismus zur Typ-Ableitung steuert, welche
Fassetten bei der Ableitung eines neuen einfachen Typs verwendet
werden können. Wenn ein einfacher Typ definiert wird, kann das
fixed
-Attribut auf jede seiner Fassetten angewendet werden, um zu verhindern, dass ein abgeleiteter Typ den Wert dieser fixierten
Fassette verändert. Wir können beispielsweise einen einfachen Typ Postleitzahl
folgendermaßen definieren:
<simpleType name="Postleitzahl"> <restriction base="string"> <length value="7" fixed="true"/> </restriction> </simpleType>
Wenn dieser einfache Typ definiert ist, können wir davon eine neue Postleitzahlen-Sorte ableiten, indem wir eine Fassette anwenden, die in der Basisdefinition nicht fixiert wurde, beispielsweise:
Postleitzahl
<simpleType name="UKPostleitzahl"> <restriction base="ibest:Postleitzahl"> <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}"/> </restriction> </simpleType>
Wir können jedoch keine neue Postleitzahlen-Sorte ableiten, in der wir eine Fassette, die in der Basisdefinition fixiert wurde, erneut anwenden:
Postleitzahl
<simpleType name="DePostleitzahl"> <restriction base="ibest:Postleitzahl"> <pattern value="\d{5}"/> <!-- unzulässiger Versuch, eine vom Basistyp fixierte Fassette anzuwenden --> <length value="5" fixed="true"/> </restriction> </simpleType>
Zusätzlich zum Mechanismus zur Steuerung der Ableitung
von Typen bietet XML Schema einen Mechanismus, der regelt, welche abgeleiteten
Typen und Ersetzungsgruppen in Instanzdokumenten verwendet
werden können. In Abschnitt 4.3 haben wir beschrieben, wie die abgeleiteten Typen DeAdresse
und USAAdresse
durch das Lieferadresse
- und das Rechnungsadresse
-Element verwendet werden konnten. Diese abgeleiteten Typen können das vom Typ Adresse
vorgesehene Inhaltsmodell ersetzen, weil sie vom Typ Adresse
abgeleitet sind. Die Ersetzung durch abgeleitete Typen kann jedoch durch Verwendung des block
-Attributs
in einer Typdefinition gesteuert werden. Wenn wir beispielsweise die Verwendung
eines durch Einschränkung abgeleiteten Typs anstelle von
Adresse
blockieren wollen (vielleicht aus demselben Grund, aus dem wir Adresse
mit final="restriction"
definiert hatten), können wir die ursprüngliche Definition von Adresse
wie folgt verändern:
<complexType name="Adresse" block="restriction"> <sequence> <element name="Name" type="string"/> <element name="Straße" type="string"/> <element name="Ort" type="string"/> </sequence> </complexType>
Der Wert restriction
des block
-Attributs verhindert, dass durch Einschränkung von Adresse
abgeleitete Typen in der Instanz Adresse
ersetzen. Dadurch würde jedoch nicht verhindert, dass USAAdresse
und DeAdresse
anstelle von Adresse
verwendet werden können, denn sie wurden durch Erweiterung abgeleitet.
Um jede Art von Ableitung oder Ableitung durch Erweiterung zu verhindern, benutzt man die Attributwerte #all
bzw. extension
. Wie bei final
gibt es ein optionales blockDefault
-Attribut auf dem schema
-Element, dessen Wert einer der für das block
-Attribut erlaubten Werte sein kann. Die Spezifikation eines blockDefault
-Attributs hat denselben Effekt wie die Spezifikation eines block
-Attributs auf jeder Typdefinition und Element-Deklaration im Schema.
Jedes Quartal schickt die Buchhandlung ihren umsatzstärksten Kunden einen Geschenkgutschein. Dafür benötigt sie eine nach Kunden gruppierte Aufstellung, welche Kunden welche Bücher erworben haben. Ein Beispiel dieser Aufstellung, für das vierte Quartal 1999, ist in 4Q99.xml zu sehen.
Beachten Sie, dass wir in diesem Abschnitt im Schema qualifizierte Namen und in den Instanzen — wo möglich — voreingestellte Namensräume verwenden.
<KundenAufstellung xmlns="http://www.example.com/Aufstellung" zeitspanne="P3M" ende="1999-12-31"> <Kundenkonto> <Kunde> <Name>Müller</Name> <Vornamen>Lieschen</Vornamen> <Geburtsdatum>1959-04-16</Geburtsdatum> <Straße>Mustergasse 29</Straße> <Ort>10178 Berlin</Ort> </Kunde> <Umsatz> <Buch ISBN="1234567893" PreisEUR="19.99"/> <Buch ISBN="3608935444" PreisEUR="49.99"/> </Umsatz> </Kundenkonto> <Kundenkonto> <Kunde> <Name>Dietrich</Name> <Vornamen>Maria Magdalene</Vornamen> <Geburtsdatum>1979-08-03</Geburtsdatum> <Straße>Am Bahndamm 5</Straße> <Ort>88410 Bad Wurzach </Ort> </Kunde> <Umsatz> <Buch ISBN="535754585X" PreisEUR="7.59"/> </Umsatz> </Kundenkonto> <Sortiment> <Buch ISBN="1234567893"> <Titel>Feine Freunde</Titel> <Autor>Donna Leon</Autor> </Buch> <Buch ISBN="535754585X"> <Titel>Deutsches Wörterbuch</Titel> <Autor>Karl-Dieter Bünting</Autor> </Buch> <Buch ISBN="3608935444"> <Titel>Der Herr der Ringe</Titel> <Autor>J.R. Tolkien</Autor> </Buch> </Sortiment> </KundenAufstellung>
Der Report führt alle Kundenkonten mit Kontaktinformation
und dem jeweiligen Umsatz (alle Bücher mit Preis) auf sowie das
komplette Sortiment mit einer Aufstellung aller Bücher.
Die Zusammenfassung ist klar und eindeutig, weil eine Reihe von Bedingungen
erfüllt sein muss. Beispielsweise darf jede Kombination von
Name, Vornamen und Geburtsdatum nur einmal auftreten (Eindeutigkeitsbeschränkung).
Genauso darf die Beschreibung jedes Buches nur einmal auftreten,
obwohl das Buch in mehreren Kundenkonten auftreten kann (Schlüsselbedingung
und referenzielle Integrität), wie zum Beispiel die ISBN-Nummer
3608935444
. Im Folgenden werden wir erläutern, wie man diese Beschränkungen mit XML Schema spezifizieren kann.
<schema targetNamespace="http://www.example.com/Aufstellung" xmlns:ibest="http://www.example.com/IBEST" xmlns:a="http://www.example.com/Aufstellung" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <!-- für ISBN --> <import namespace="http://www.example.com/IBEST"/> <annotation> <documentation xml:lang="DE"> Kundenaufstellung Schema für Example.com. Copyright 2000 Example.com. Alle Rechte vorbehalten. </documentation> </annotation> <element name="KundenAufstellung"> <complexType> <sequence> <element name="Kundenkonto" type="a:KundenkontoTyp" maxOccurs="unbounded"> <keyref name="Schlüssel2" refer="a:ISchlüssel"> <selector xpath="a:Umsatz/a:Buch"/> <field xpath="@ISBN"/> </keyref> </element> <element name="Sortiment" type="a:SortimentTyp" maxOccurs="unbounded"/> </sequence> <attribute name="zeitspanne" type="duration"/> <attribute name="ende" type="date"/> </complexType> <unique name="EindBeschr1"> <selector xpath="a:Kundenkonto/a:Kunde"/> <field xpath="a:Name"/> <field xpath="a:Vornamen"/> <field xpath="a:Geburtsdatum"/> </unique> <key name="ISchlüssel"> <selector xpath="a:Sortiment/a:Buch"/> <field xpath="@ISBN"/> </key> </element> <complexType name="KundenkontoTyp"> <sequence> <element name="Kunde"> <complexType> <sequence> <element name="Name" type="string"/> <element name="Vornamen" type="string"/> <element name="Geburtsdatum" type="date"/> <element name="Straße" type="string"/> <element name="Ort" type="string"/> </sequence> </complexType> </element> <element name="Umsatz"> <complexType> <sequence> <element name="Buch" maxOccurs="unbounded"> <complexType> <complexContent> <restriction base="anyType"> <attribute name="ISBN" type="ibest:ISBNTyp"/> <attribute name="PreisEUR" type="decimal"/> </restriction> </complexContent> </complexType> </element> </sequence> </complexType> </element> </sequence> </complexType> <complexType name="SortimentTyp"> <sequence> <element name="Buch" maxOccurs="unbounded"> <complexType> <sequence> <element name="Titel" type="string"/> <element name="Autor" type="string"/> </sequence> <attribute name="ISBN" type="ibest:ISBNTyp"/> </complexType> </element> </sequence> </complexType> </schema>
Mit XML Schema kann man festlegen, dass der Wert eines
beliebigen Attributs oder Elements innerhalb eines gewissen Bereichs
eindeutig sein muss. Um diese Eindeutigkeit
für ein Attribut oder Element zu spezifizieren, verwenden wir das unique
-Element, um zuerst eine Menge von Elementen auszuwählen, und dann das field
-Element, um das fragliche Attribut oder Element relativ zu den ausgewählten Elementen zu identifizieren; das Element oder
Attribut muss dann im Bereich der ausgewählten Elemente eindeutig sein.
Angenommen, Kunden werden durch eine eindeutige Nummer identifiziert:
Das xpath
-Attribut des selector
-Elements enthält einen XPath-Ausdruck, Kunden/Kunde
, der eine Liste aller Kunde
-Elemente in einer Instanz auswählt. Das xpath
-Attribut des field
-Elements spezifiziert einen weiteren XPath-Ausdruck, @Kundennummer
, der festlegt, dass das Attribut Kundennummer
eindeutig sein muss. Der XPath-Ausdruck schränkt den Bereich ein, innerhalb
dessen Eindeutigkeit herrschen muss. Die Aufstellung könnte
noch ein anderes Kundennummer
-Attribut enthalten, sein Wert müsste jedoch nicht eindeutig sein, weil es außerhalb des durch den XPath-Ausdruck definierten
Bereichs läge. Beachten Sie, dass für die XPath-Ausdrücke, die für das xpath
-Attribut verwendet werden können, nur eine Untermenge der vollen XPath-Sprache, wie sie in XML Path Language 1.0 definiert wird, zur Verfügung steht.
Man kann auch Kombinationen von Feldern als eindeutig definieren, in 4Q99.xml die Kombination aus Name
, Vornamen
und Geburtsdatum
von Kunde
. Dazu fügen wir für jeden Wert der Kombination ein field
-Element hinzu:
<unique name="EindBeschr1"> <selector xpath="a:Kundenkonto/a:Kunde"/> <field xpath="a:Name"/> <field xpath="a:Vornamen"/> <field xpath="a:Geburtsdatum"/> </unique>
In der Kundenaufstellung für das 4. Quartal 1999 taucht
die Beschreibung jedes Buchs im Sortiment nur einmal auf. Wir könnten
diese Beschränkung mit unique
erreichen, aber wir wollen zusätzlich noch sicherstellen, dass jedes im Umsatz eines Kunden auftretende Buch
-Element auch im Sortiment vorhanden ist. Diese Beschränkung lässt sich mit den Elementen key
und keyref
ausdrücken. Im Schema für die Kundenaufstellung, aufst.xsd, sieht man, dass die key
- und keyref
-Konstrukte fast genauso wie das unique
-Konstrukt angewendet werden. Das key
-Element bezieht sich auf das ISBN
-Attribut der Buch
-Elemente, die als Kind von Sortiment
auftreten. Diese Definition von ISBN
als Schlüssel impliziert, dass der Wert eindeutig und von Nil verschieden (das Attribut nillable
darf nicht true
sein) sein muss. Der mit dem Schlüssel assoziierte Name, ISchlüssel
, sorgt dafür, dass der Schlüssel von anderer Stelle aus referenziert werden kann.
Um sicherzustellen, dass die Umsatz/Buch
-Elemente entsprechende Sortiment/Buch
-Elemente haben, legen wir fest, dass das ISBN
-Attribut (<field xpath="@ISBN"/>
) dieser Elemente (<selector xpath="a:Umsatz/a:Buch"/>
) den Schlüssel ISchlüssel
referenziert. Diese Deklaration von ISBN
als Schlüsselreferenz (keyref
) bedeutet nicht, dass der Wert eindeutig sein muss, sondern nur, dass es einen ISchlüssel
mit demselben Wert geben muss.
Wie Sie vielleicht schon geahnt haben, gibt es analog zu unique
die Möglichkeit, zusammengesetzte key
- und keyref
-Werte
zu definieren. Mit diesem Mechanismus kann man auch mehr tun als nur die
ISBN-Nummern gleich zu machen, nämlich eine Kombination
von Werten definieren, die gleich sein müssen. Dabei können auch Werte mit
verschiedenen Typen kombiniert werden (string
,
integer
,
date
usw.), vorausgesetzt, Ordnung und Typ der mit field
referenzierten Elemente sind in den Definitionen für key
und keyref
gleich.
In XML 1.0 gibt es einen Mechanismus, um Eindeutigkeit unter Verwendung des ID-Attributs und der damit assoziierten Attribute IDREF
und IDREFS herzustellen. Denselben Mechanismus gibt es auch in XML Schema durch die einfachen Typen ID, IDREF und IDREFS,
die für die Deklaration von Attributen im Stil von XML 1.0 verwendet werden
können. Die von XML Schema außerdem neu eingeführten Mechanismen
sind flexibler und mächtiger. Beispielsweise können die XML Schema Mechanismen
auf jedes Element oder Attribut angewendet werden, unabhängig
von dessen Typ. Im Gegensatz dazu ist ID selbst eine Art von Attribut
und kann deshalb nicht auf Attribute, Elemente oder deren Inhalt angewendet
werden. Außerdem kann man mit Schema den Gültigkeitsbereich
für eine Eindeutigkeitsbeschränkung angeben, während ein ID-Attribut
immer über das gesamte Dokument eindeutig sein muss. Und
letztlich erlaubt es XML Schema noch, Schlüssel (key
) und Fremdschlüssel (keyref
) aus Kombinationen von Elementen und Attributen zu erzeugen, während ID keine solche Möglichkeit bietet.
Das Schema für die Kundenaufstellung, aufst.xsd, verwendet einen einfachen Typ, ibest:ISBNTyp
, der in einem anderen Schema definiert wird und in einem anderen Ziel-Namensraum ist. Erinnern Sie sich, wir haben include
benutzt, damit das Schema in ibest.xsd die Definitionen und Deklarationen aus adresse.xsd verwenden konnte. Hier können wir include
nicht verwenden, weil es nur Definitionen und Deklarationen aus einem Schema
mit demselben Ziel-Namensraum wie das inkludierende Schema
hereinholen kann. Deshalb nennt das include
-Element auch keinen Namensraum (auch wenn es eine schemaLocation
benötigt). Der Import-Mechanismus, den wir in diesem Abschnitt beschreiben,
ist eine wichtige Technik, die es erlaubt, Schemakomponenten
aus unterschiedlichen Ziel-Namensräumen zusammen zu verwenden, und
die so eine Schema-Validierung von Instanzdokumenten, deren
Inhalt aus verschiedenen Namensräumen stammt, ermöglicht.
Um den Typ ISBNTyp
zu importieren und im Schema für die Kundenaufstellung zu verwenden, geben wir den Namensraum, in dem ISBNTyp
definiert ist, an und assoziieren ihn mit einem Präfix für die Benutzung im Schema für die Kundenaufstellung. Konkret benutzen
wir das import
-Element, um den Ziel-Namensraum von ISBNTyp
, http://www.example.com/intBest
, zu definieren und assoziieren diesen Namensraum mittels einer Standard-Namensraumdeklaration mit dem Präfix ibest:
. Der einfache Typ ISBNTyp
, im Namensraum http://www.example.com/intBest
definiert, kann in den Definitionen und Deklarationen im Schema der Kundenaufstellung als ibest:ISBNTyp
referenziert werden.
In unserem Beispiel haben wir einen einfachen Typ aus einem
externen Namensraum importiert und ihn für die Deklaration von
Attributen verwendet. Tatsächlich erlaubt XML Schema den Import
von beliebig vielen Schemakomponenten aus beliebig vielen
Namensräumen und sie können in Deklarationen und in Definitionen verwendet
werden. Beispielsweise könnten wir in aufst.xsd zusätzlich das Kommentar
-Element, das in ibest.xsd definiert wird, wiederverwenden, indem wir es in einer Deklaration referenzieren:
<element ref="ibest:Kommentar"/>
Beachten Sie jedoch, dass wir das Lieferadresse
-Element aus best.xsd nicht wiederverwenden können, weil nur globale Schemakomponenten importiert werden können und deshalb Folgendes nicht erlaubt ist:
<element ref="ibest:Lieferadresse"/>
In ibest.xsd ist Kommentar
als globales Element deklariert, mit anderen Worten, es wird als Kindelement von schema
deklariert. Im Gegensatz dazu wird Lieferadresse
lokal deklariert, d.h, das Element wird innerhalb der Definition eines komplexen Typs deklariert, genauer gesagt innerhalb
des Typs BestellungTyp
.
Man kann auch komplexe Typen importieren, und sie können
als Basistyp für die Ableitung neuer Typen verwendet werden. Nur
benannte komplexe Typen können importiert werden, bei lokalen,
anonym definierten Typen ist dies nicht möglich. Angenommen,
wir wollen in unserer Aufstellung den Namen eines Verantwortlichen
angeben, zusammen mit einer Kontaktinformation. Wir können
dafür den (global definierten) Typ DeAdresse
aus adresse.xsd wiederverwenden und ihn zu einem neuen Typ, VerantwortlicherType
, erweitern, indem wir die neuen Elemente Telefonnr
und E-Mail
hinzufügen:
VerantwortlicherType
durch Erweiterung von DeAdresse
<complexType name="VerantwortlicherType"> <complexContent> <extension base="ibest:DeAdresse"> <sequence> <element name="Telefonnr" type="string"/> <element name="E-Mail" type="string"/> </sequence> </extension> </complexContent> </complexType>
Mit diesem neuen Typ deklarieren wir ein Element namens Verantwortlicher
als Teil der Deklaration des KundenAufstellung
-Elements (Deklarationen sind nicht gezeigt) im Schema für die Kundenaufstellung. Dann würde folgendes Instanzdokument dem
modifizierten Schema entsprechen:
VerantwortlicherType
entsprechendes Instanzdokument
<KundenAufstellung xmlns="http://www.example.com/Aufstellung" zeitspanne="P3M" ende="1999-12-31"> <!-- Die Teile Kundenkonto und Sortiment sind ausgelassen --> <Verantwortlicher> <Name>Lieschen Müller</Name> <Straße>Lerchenweg 17</Straße> <Ort>Frankfurt/Main</Ort> <PLZ>61240</PLZ> <Telefonnr>0815 4711</Telefonnr> <E-Mail>Lieschen.Mueller@example.com</E-Mail> </Verantwortlicher> </KundenAufstellung>
Wenn Schemakomponenten aus verschiedenen Namensräumen importiert
werden, muss jeder Namensraum mit einem eigenen import
-Element gekennzeichnet werden. Die import
-Elemente selbst müssen als die ersten Kind-Elmente des schema
-Elements
auftreten. Außerdem muss jeder Namensraum über eine normale Namensraum-Deklaration
mit einem Präfix assoziiert werden, welches benutzt wird,
um Referenzen auf Schemakomponenten aus diesem Namensraum zu qualifizieren.
Das import
-Element kann ein optionales schemaLocation
-Attribut haben, um das Auffinden der mit dem Namensraum assoziierten Ressourcen zu erleichtern. Wir werden das schemaLocation
Attribut in einem späteren Abschnitt detailliert besprechen.
Mit der weiteren Verbreitung von XML Schema werden Schema-Autoren einfache und komplexe Typen erzeugen, mit anderen Autoren teilen und als Bausteine für neue Schemata nutzen wollen. XML Schema bietet bereits Typen, die diese Rolle spielen können, beschrieben in Anhang B Einfache Typen und ihre Fassetten sowie in der XML Schema Typbibliothek.
Schema-Autoren werden zweifellos ihre eigenen Typbibliotheken erstellen wollen, etwa mit Typen für die Repräsentation von Währungen, Maßeinheiten, Geschäftsadressen usw. Jede Bibliothek könnte aus einem Schema mit einer oder mehreren Definitionen bestehen, zum Beispiel einem Schema, das einen Währungstyp enthält:
<schema targetNamespace="http://www.example.com/Währung" xmlns:c="http://www.example.com/Währung" xmlns="http://www.w3.org/2001/XMLSchema"> <annotation> <documentation xml:lang="DE"> Definition eines Währungstyps auf Basis von ISO 4217 </documentation> </annotation> <complexType name="Währung"> <simpleContent> <extension base="decimal"> <attribute name="name"> <simpleType> <restriction base="string"> <enumeration value="AED"> <annotation> <documentation xml:lang="DE"> Vereinigte Arabische Emirate: Dirham (1 Dirham = 100 Fils) </documentation> </annotation> </enumeration> <enumeration value="AFA"> <annotation> <documentation xml:lang="DE"> Afghanistan: Afghani (1 Afghani = 100 Puls) </documentation> </annotation> </enumeration> <enumeration value="ALL"> <annotation> <documentation xml:lang="DE"> Albanien, Lek (1 Lek = 100 Qindarka) </documentation> </annotation> </enumeration> <!-- ... und alle anderen Währungen --> </restriction> </simpleType> </attribute> </extension> </simpleContent> </complexType> </schema>
Ein Beispiel für ein Element dieses Typs in einer Instanz wäre:
<umrechnenAus name="AFA">199.37</umrechnenAus>
Nachdem der Währungstyp definiert wurde, kann er in anderen Schemata über den beschriebenen import
-Mechanismus wiederverwendet werden.
In den vorherigen Abschnitten haben wir einige Mechanismen für die Erweiterung des Inhaltsmodells von komplexen Typen besprochen. So kann beispielsweise ein gemischtes Inhaltsmodell zusätzlich zu Elementen beliebige Zeichendaten enthalten und ein Inhaltsmodell kann Elemente enthalten, deren Typen aus externen Namensräumen importiert sind. Diese Mechanismen bieten jedoch nur eine sehr lose respektive sehr strenge Kontrolle. Das Ziel dieses Abschnitts ist es, einen flexiblen Mechanismus zu beschreiben, mit dem man ein Inhaltsmodell um beliebige Attribute oder Elemente erweitern kann, die zu einem spezifizierten Namensraum gehören.
Zur Verdeutlichung betrachten wir eine Version der Kundenaufstellung, 4Q99html.xml, in die wir eine HTML-Repräsentation der Sortiment-Daten eingebettet haben. Der HTML-Inhalt erscheint als Inhalt des Elements
htmlBsp
, und beim äußersten HTML-Element (table
) wird der voreingestellte Namensraum verändert, so dass alle HTML-Elemente zum HTML-Namensraum http://www.w3.org/1999/xhtml
gehören:
<KundenAufstellung xmlns="http://www.example.com/Aufstellung" zeitspanne="P3M" ende="1999-12-31"> <Kundenkonto> <!-- Umsatz nach Kunde geordnet, Daten aus 4Q99.xml --> </Kundenkonto> <Sortiment> <!-- Bücher aus 4Q99.xml --> </Sortiment> <htmlBsp> <table xmlns="http://www.w3.org/1999/xhtml" border="0" width="100%"> <tr> <th align="left">Kunde</th> <th align="left">Buch</th> <th align="left">Preis</th> </tr> <tr><td>Lieschen Müller</td><td> </td><td> </td></tr> <tr><td> </td><td>1234567893</td><td>19.99/</td></tr> <tr><td> </td><td>3608935444</td><td>49.99</td></tr> <tr><td>Maria Magdalene</td><td> </td><td> </td></tr> <tr><td> </td>535754585X<td></td><td></td>7.59</tr> </table> </htmlBsp> </KundenAufstellung>
Um die Verwendung von HTML im Instanzdokument zu erlauben,
modifizieren wir das Schema für die Kundenaufstellung, indem wir
ein neues Element htmlBsp
deklarieren, dessen Inhalt durch das any
-Element definiert wird. Allgemein spezifiziert das any
-Element, dass im Inhaltsmodell des Typs jedes wohlgeformte XML zulässig ist. Im Beispiel verlangen wir außerdem, dass das
XML zum Namensraum http://www.w3.org/1999/xhtml
gehört, mit anderen Worten, es soll HTML sein. Das Beispiel fordert außerdem,
dass es mindestens ein Element aus diesem Namensraum geben
muss, wie durch die Werte für minOccurs
und maxOccurs
angegeben:
Kundenaufstellung
, um HTML zu erlauben
<element name="KundenAufstellung"> <complexType> <sequence"> <element name="Kundenkonto" type="a:KundenkontoTyp" maxOccurs="unbounded"> <element name="Kundenkonto" type="a:KundenkontoTyp" maxOccurs="unbounded"> <element name="htmlBsp"> <complexType> <sequence> <any namespace="http://www.w3.org/1999/xhtml" minOccurs="1" maxOccurs="unbounded" processContents="skip"/> </sequence> </complexType> </element> </sequence> </complexType> </element>
Die Modifikation erlaubt, dass wohlgeformtes XML aus dem Namensraum http://www.w3.org/1999/xhtml
innerhalb des htmlBsp
-Elements auftritt. Das Beispiel 4Q99html.xml ist zulässig, denn es enthält ein Element, das (inklusive seiner Kindelemente) wohlgeformt ist, das Element erscheint innerhalb
des richtigen Elements (htmlBsp
) und das Instanzdokument sichert zu, dass das Element und sein Inhalt zum vorgeschriebenen Namensraum gehören. Das HTML muss
jedoch nicht unbedingt gültig sein, denn nichts in 4Q99html.xml alleine kann diese Garantie geben. Wenn so eine Garantie benötigt wird, sollte der Wert des processContents
-Attributs auf strict
gesetzt werden (dem Vorgabe-Wert). In diesem Fall ist der XML-Prozessor dazu
verpflichtet, das mit dem vorgeschriebenen Namensraum assoziierte
Schema zu erlangen, und das HTML innerhalb des htmlBsp
-Elements zu validieren.
In einem anderen Beispiel definieren wir einen Text
-Typ, ähnlich dem Text-Typ, der in XML Schemas einführender Typbibliothek definiert wird (siehe auch Abschnitt 5.4.1) und der für internationalisierten, menschen-lesbaren Text geeignet ist. Der Text-Typ erlaubt eine uneingeschränkte Mischung
aus Zeichen-Inhalt und Element-Inhalt aus jedem beliebigen Namensraum, zum Beispiel Ruby-Annotationen, zusammen mit einem optionalen xml:lang
-Attribut. Der Wert lax
des processContents
-Attributs
weist einen XML-Prozessor an, das Element zu validieren, falls er dazu in
der Lage ist: Er wird dann Elemente und Attribute validieren,
für die er Schema-Information erlangen kann, aber für diejenigen, wo dies
nicht möglich ist, keine Fehler melden.
<xsd:complexType name="Text"> <xsd:complexContent mixed="true"> <xsd:restriction base="xsd:anyType"> <xsd:sequence> <xsd:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> <xsd:attribute ref="xml:lang"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType>
Namensräume können verwendet werden, um Element-Inhalt
auf verschiedene Weise zu erlauben oder zu verbieten, je nach Wert
des namespace
-Attributs, wie in Tabelle 4 gezeigt:
Zusätzlich zum any
-Element, welches Element-Inhalt nach Namensraum ermöglicht, gibt es ein korrespondierendes anyAttribute
-Element, das Attribute in Elementen ermöglicht. Beispielsweise können wir beliebige HTML-Attribute als Teil von htmlBsp
erlauben, indem wir anyAttribute
zu seiner Deklaration hinzufügen:
htmlBsp
, um HTML Attribute zu erlauben
<element name="htmlBsp"> <complexType> <sequence> <any namespace="http://www.w3.org/1999/xhtml" minOccurs="1" maxOccurs="unbounded" processContents="skip"/> </sequence> <anyAttribute namespace="http://www.w3.org/1999/xhtml"/> </complexType> </element>
Diese Deklaration erlaubt das Erscheinen eines HTML Attributs, etwa href
, im Element htmlBsp
, zum Beispiel:
htmlBsp
-Element
.... <htmlBsp xmlns:h="http://www.w3.org/1999/xhtml" h:href="http://www.example.com/Aufstellungen/4Q99.html"> <!-- weiteres HTML-Markup --> </htmlBsp> ....
Das namespace
-Attribut des anyAttribute
-Elements kann auf jeden der in Tabelle 4 für das any
-Element angegebenen Werte gesetzt werden, und auch anyAttribute
kann mit einem processContents
-Attribut spezifiziert werden. Im Gegensatz zum any
-Element kann anyAttribute
jedoch die Anzahl der Attribute, die in einem Element erscheinen können, nicht beschränken.
XML Schema benutzt die Attribute schemaLocation
und xsi:schemaLocation
in drei Fällen.
1. In einem Instanzdokument bietet das Attribut schemaLocation
Hinweise des Autors an einen Schema-Prozessor hinsichtlich der Lokation
des Schema-Dokuments. Der Autor garantiert, dass diese
Schema-Dokumente für eine Gültigkeitsprüfung des Dokumentinhalts auf Basis
von Namensräumen relevant sind. Zum Beispiel können wir
einem Prozessor, der die Kundenaufstellung verarbeitet, einen Hinweis auf
die Lokation des Schemas für die Kundenaufstellung geben:
schemaLocation
in der Kundenaufstellung, 4Q99html.xml
<KundenAufstellung xmlns="http://www.example.com/Aufstellung" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/Aufstellung http://www.example.com/aufst.xsd" zeitspanne="P3M" ende="1999-12-31"> <!-- usw. --> </KundenAufstellung>
Das schemaLocation
-Attribut
enthält Wertepaare aus einem Namensraum und einem URI. Dieser ist ein
Hinweis, der beschreibt, wo man ein geeignetes Schema-Dokument
für den Namensraum finden kann. Das Vorhandensein dieser Hinweise verpflichtet
den Schema-Prozessor jedoch nicht, das angegebene Schema-Dokument
zu erlangen oder zu benutzen, und der Prozessor kann auch andere Schemata
benutzen, die er auf angemessenem Weg erhalten hat, oder
überhaupt kein Schema.
Ein Schema muss keinen Namensraum haben (siehe Kapitel 3.4), und deshalb gibt es ein noNamespaceSchemaLocation
-Attribut, das verwendet wird, um einen Hinweis auf die Lokation von Schema-Dokumenten ohne Ziel-Namensraum zu geben.
2. In einem Schema hat das include
-Element ein vorgeschriebenes schemaLocation
-Attribut,
welches eine URI-Referenz enthält, die ein Schema-Dokument identifizieren
muss. Als Effekt wird das letztendlich wirksame Schema
zusammengesetzt, indem die Deklarationen und Definitionen des inkludierenden
und des inkludierten Schemas zusammengeführt werden. Beispielsweise
werden in Kapitel 4 die Typdefinitionen von Adresse
, DeAdresse
, USAAdresse
und USBundesstaat
(einschließlich ihrer Attribute und lokalen Element-Deklarationen) aus adresse.xsd mit den Element-Deklarationen von KundenAufstellung
und Kommentar
und den Typdefinitionen von BestellungTyp
, Waren
und ISBNTyp
(einschließlich ihrer Attribute und lokalen Element-Deklarationen) aus ibest.xsd zusammengefügt, um ein einziges Schema zu bilden.
3. Ebenfalls in einem Schema hat das import
-Element optionale namespace
und schemaLocation
-Attribute. Falls vorhanden, wird schemaLocation
so verstanden, dass seine Interpretation der Interpretation des xsi:schemaLocation
-Attributs
in (1) gleichkommt. Genauer gesagt, es stellt einen Hinweis des Autors an
den Schema-Prozessor auf die Lokation eines Schema-Dokuments
dar. Für dieses Schema garantiert der Autor, dass es die benötigten Definitionen
und Deklarationen enthält, um die Komponenten aus dem durch
das namespace
-Attribut spezifizierten Namensraum zu validieren.
Um Komponenten zu importieren, die nicht in einem Ziel-Namensraum sind, wird das import
-Element ohne namespace
-Attribut (und mit oder ohne schemaLocation
-Attribut) verwendet. Referenzen auf so importierte Komponenten erfolgen nicht qualifiziert.
Beachten Sie, dass schemaLocation
nur ein Hinweis ist und einige Prozessoren und Applikationen ihre Gründe haben werden, ihn nicht zu benutzen. Beispielsweise
könnte ein HTML-Editor ein eingebautes HTML-Schema bevorzugen.
Ein Instanzdokument kann zusammen mit einem Schema verarbeitet werden, um zu überprüfen, ob die im Schema spezifizierten Regeln in der Instanz eingehalten werden. Typischerweise erleidigt eine solche Verarbeitung zwei Dinge: Sie prüft erstens auf Einhaltung der Regeln (ein Prozess, der Schema-Validation genannt wird) und fügt zweitens ergänzende Information hinzu, die in der Instanz nicht unmittelbar vorhanden ist, wie Typinformation und Vorgabe-Werte, so genannte Infoset-Beiträge (Infoset Contributions).
Der Autor eines Instanzdokuments, etwa einer bestimmten Buchbestellung,
kann in der Instanz selbst behaupten, dass sie den Regeln
eines bestimmten Schemas entspricht. Dies geschieht durch die Verwendung
des oben beschriebenen schemaLocation
-Attributs. Aber unabhängig davon, ob es ein schemaLocation
-Attribut
gibt, hat eine Anwendung die Freiheit, ein Dokument gegen ein beliebiges
Schema zu prüfen. Eine Einkaufsapplikation könnte zum Beispiel
eine Regelung haben, nach der immer ein bestimmtes Schema für Buchbestellungen
verwendet wird, egal ob es andere Werte für schemaLocation
gibt.
Die Prüfung auf Konformität kann als schrittweises Vorgehen betrachtet werden, bei dem zuerst geprüft wird, ob das Wurzel-Element einer Dokument-Instanz den richtigen Inhalt hat, dann, ob alle Subelemente ihrer Beschreibung im Schema entsprechen, usw., bis das gesamte Dokument verifiziert ist. Prozessoren sind verpflichtet anzugeben, welche Überprüfungen ausgeführt wurden.
Um ein Element auf Konformität zu prüfen, muss der Prozessor zuerst
die Lokation der Deklaration für das Element in einem Schema
ausfindig machen und dann überprüfen, ob das targetNamespace
-Attribut im Schema mit dem tatsächlichen Namensraum-URI des Elements übereinstimmt. Alternativ kann er feststellen, dass
das Schema kein targetNamespace
-Attribut hat, und das Instanz-Element nicht qualifiziert ist.
Falls die Namensräume übereinstimmen, untersucht der Prozessor
als Nächstes den Typ des Elements, wie er entweder durch die
Deklaration im Schema vorgegeben ist oder durch ein xsi:type
-Attribut in der Instanz. Ist letzteres der Fall, so muss der Typ in der Instanz eine zulässige Ersetzung für den im Schema
festgelegten Typ sein; was zulässig ist, wird durch das block
-Attribut in der Element-Deklaration bestimmt. Gleichzeitig werden Vorgabe-Werte und andere Infoset-Beiträge angewendet.
Als nächstes überprüft der Prozessor die direkten Attribute
und Inhalte des Elements, indem er sie mit den Attributen und
Elementen vergleicht, die der Typ des Elements erlaubt. Betrachten
wir beispielsweise ein Lieferadresse
-Element, wie das aus Kapitel 2.1: Der Prozessor prüft, welche Regeln für eine DeAdresse
gelten, weil das Lieferadresse
-Element diesen Typ hat.
Wenn das Element einen einfachen Typ hat, verifiziert der Prozessor, dass das Element keine Attribute oder enthaltene Elemente besitzt und dass der Zeichen-Inhalt den Regeln des einfachen Typs entspricht. Dies schließt manchmal die Prüfung der Zeichenkette gegen reguläre Ausdrücke oder Aufzählungen ein und manchmal umfasst es die Prüfung, ob die Zeichenkette einen Wert aus dem erlaubten Wertebereich repräsentiert.
Wenn das Element einen komplexen Typ hat, überprüft der Prozessor, ob alle vorgeschriebenen Attribute vorhanden sind und ob ihre Werte den Auflagen ihrer einfachen Typen entsprechen. Er prüft außerdem, ob alle vorgeschriebenen Subelemente vorhanden sind und ob die Folge von Subelementen (und gemischtem Text) dem Inhaltsmodell, das für den komplexen Typ deklariert wurde, entspricht. Was Subelemente betrifft, so können Schemata entweder exakte Übereinstimmung der Namen fordern, Ersetzung durch ein äquivalentes Element erlauben oder Ersetzung durch jedes Element erlauben, das durch einen 'any'-Partikel gestattet wird.
Wenn das Schema es nicht anders vorsieht (wie es durch 'any'-Partikel möglich ist), geht die Prüfung auf Konformität dann eine Ebene tiefer weiter, indem der Reihe nach unter Wiederholung des oben geschilderten Prozesses jedes Subelement betrachtet wird.
Viele Helfer haben mit Ideen, Material und Feedback zur Verbesserung dieses Dokuments beigetragen. Insbesondere möchten sich die Herausgeber [des Originaldokuments] für Beiträge von David Beech, Paul Biron, Don Box, Allen Brown, David Cleary, Dan Connolly, Roger Costello, Martin Dürst, Martin Gudgin, Dave Hollander, Joe Kesselman, John McCarthy, Andrew Layman, Eve Maler, Ashok Malhotra, Noah Mendelsohn, Michael Sperberg-McQueen, Henry Thompson, Misha Wolf und bei Priscilla Walmsley für die Validierung der Beispiele bedanken.
Die für jeden einfachen Typ erlaubten Werte lassen sich durch die Anwendung einer oder mehrerer Fassetten einschränken. In Tabelle B1.a und B1.b sind alle vordefinierten einfachen Typen von XML Schema zusammen mit den darauf anwendbaren Fassetten aufgeführt. Die Namen der einfachen Typen und die der Fassetten sind mit der jeweiligen Definition in “XML Schema Teil 2: Datentypen” verlinkt.
Tabelle B1.a. Einfache Typen und darauf anwendbare Fassetten | ||||||
---|---|---|---|---|---|---|
einfacher Typ | Fassette | |||||
length | minLength | maxLength | pattern | enumeration | whiteSpace | |
string | X | X | X | X | X | X |
normalizedString | X | X | X | X | X | X |
token | X | X | X | X | X | X |
byte | X | X | X | |||
unsignedByte | X | X | X | |||
base64Binary | X | X | X | X | X | X |
hexBinary | X | X | X | X | X | X |
integer | X | X | X | |||
positiveInteger | X | X | X | |||
negativeInteger | X | X | X | |||
nonNegativeInteger | X | X | X | |||
nonPositiveInteger | X | X | X | |||
int | X | X | X | |||
unsignedInt | X | X | X | |||
long | X | X | X | |||
unsignedLong | X | X | X | |||
short | X | X | X | |||
unsignedShort | X | X | X | |||
decimal | X | X | X | |||
float | X | X | X | |||
double | X | X | X | |||
boolean | X | X | ||||
time | X | X | X | |||
dateTime | X | X | X | |||
duration | X | X | X | |||
date | X | X | X | |||
gMonth | X | X | X | |||
gYear | X | X | X | |||
gYearMonth | X | X | X | |||
gDay | X | X | X | |||
gMonthDay | X | X | X | |||
Name | X | X | X | X | X | X |
QName | X | X | X | X | X | X |
NCName | X | X | X | X | X | X |
anyURI | X | X | X | X | X | X |
language | X | X | X | X | X | X |
ID | X | X | X | X | X | X |
IDREF | X | X | X | X | X | X |
IDREFS | X | X | X | X | X | |
ENTITY | X | X | X | X | X | X |
ENTITIES | X | X | X | X | X | |
NOTATION | X | X | X | X | X | X |
NMTOKEN | X | X | X | X | X | X |
NMTOKENS | X | X | X | X | X |
Die in Tabelle B1.b aufgeführten Fassetten lassen sich nur auf geordnete einfache Typen anwenden, weshalb diese Tabelle nicht alle einfachen Typen enthält.
Tabelle B1.b. Einfache Typen und darauf anwendbare Fassetten | ||||||||
---|---|---|---|---|---|---|---|---|
einfache Typen | Fassetten | |||||||
maxInclusive | maxExclusive | minInclusive | minExclusive | totalDigits | fractionDigits | |||
byte | X | X | X | X | X | X | ||
unsignedByte | X | X | X | X | X | X | ||
integer | X | X | X | X | X | X | ||
positiveInteger | X | X | X | X | X | X | ||
negativeInteger | X | X | X | X | X | X | ||
nonNegativeInteger | X | X | X | X | X | X | ||
nonPositiveInteger | X | X | X | X | X | X | ||
int | X | X | X | X | X | X | ||
unsignedInt | X | X | X | X | X | X | ||
long | X | X | X | X | X | X | ||
unsignedLong | X | X | X | X | X | X | ||
short | X | X | X | X | X | X | ||
unsignedShort | X | X | X | X | X | X | ||
decimal | X | X | X | X | X | X | ||
float | X | X | X | X | ||||
double | X | X | X | X | ||||
time | X | X | X | X | ||||
dateTime | X | X | X | X | ||||
duration | X | X | X | X | ||||
date | X | X | X | X | ||||
gMonth | X | X | X | X | ||||
gYear | X | X | X | X | ||||
gYearMonth | X | X | X | X | ||||
gDay | X | X | X | X | ||||
gMonthDay | X | X | X | X |
XML 1.0 bietet verschiedene Typen von benannten Inhaltsfragmenten, genannt Entities, die bei der Erstellung von DTDs (Parameter-Entities) oder Instanzdokumenten verwendet werden können. In Kapitel 2.7 haben wir darauf hingewiesen, wie benannte Gruppen das Verhalten von Parameter-Entities nachbilden. In diesem Kapitel zeigen wir, wie Entities in Instanzdokumenten deklariert werden können und wie die den Entities entsprechende Funktionalität in Schemata deklariert werden kann.
Angenommen, wir wollen in einem Instanzdokument eine Entity deklarieren und benutzen, und dieses Instanzdokument ist zusätzlich durch ein Schema beschränkt. Ein Beispiel:
<?xml version="1.0" ?> <!DOCTYPE Bestellung [ <!ENTITY eacute "é"> ]> <Bestellung xmlns="http://www.example.com/best1" bestelldatum="1999-10-20"> <!-- usw. --> <Stadt>Montréal</Stadt> <!-- usw. --> </Bestellung>
Hier deklarieren wir eine Entity namens eacute
als Teil eines internen (DTD) Subsets und referenzieren diese Entity im Inhalt des Stadt
-Elements. Beachten Sie, dass bei der Verarbeitung des Instanzdokuments die Entity vor der Schema-Validierung dereferenziert
wird. Mit anderen Worten, bei der Überprüfung der Gültigkeit des Stadt
-Elements verwendet der Schema-Prozessor Montréal
als Wert des Elements.
Ein ähnliches (aber nicht identisches) Ergebnis kann man erreichen, indem man ein Element in einem Schema deklariert und seinen Inhalt entsprechend setzt:
<xsd:element name="eacute" type="xsd:token" fixed="é"/>
Dieses Element kann dann in einem Instanzdokument verwendet werden:
<?xml version="1.0" ?> <Bestellung xmlns="http://www.example.com/best1" xmlns:c="http://www.example.com/ZeichenElemente" bestelldatum="1999-10-20"> <!-- usw. --> <Stadt>Montr<c:eacute/>al</Stadt> <!-- usw. --> </Bestellung>
In diesem Fall verarbeitet ein Schema-Prozessor zwei Elemente, ein Stadt
-Element und ein eacute
-Element, für dessen Inhalt der Prozessor ein einziges é
-Zeichen
einfügt. Beachten Sie, dass das zusätzliche Element den Vergleich von Zeichenketten
verkompliziert: Die beiden Formen des Namens “Montréal” aus
den beiden Beispielen wären nicht gleich, wenn man die üblichen Operationen
für den Vergleich von Zeichenketten verwendet.
Die pattern
-Fassette von XML Schema verwendet eine Sprache für reguläre Ausdrücke, die Unicode unterstützt. Sie ist in “XML Schema Teil 2: Datentypen“ vollständig beschrieben. Die Sprache ist der in der Programmiersprache Perl
verwendeten Sprache für reguläre Ausdrücke sehr ähnlich, auch wenn Ausdrücke
mit vollständigen lexikalischen Repräsentationen verglichen
werden, nicht nur mit vom Benutzer bestimmten Geltungsbereichen wie Zeile
oder Absatz. Aus diesem Grund sind die Metazeichen ^ und $
nicht in der Sprache enthalten, ^ wird jedoch benutzt, um Ausschlüsse auszudrücken,
wie im Ausdruck [^0-9]x.
Tabelle D1. Beispiele für reguläre Ausdrücke | |
---|---|
Ausdruck | passende Zeichenketten |
Kapitel \d | Kapitel 0, Kapitel 1, Kapitel 2 .... |
Kapitel \s\d | Kapitel gefolgt von genau einem Leerraum-Zeichen (Leerzeichen, Tabulator, neue Zeile, usw.), gefolgt von genau einer Ziffer |
Kapitel \s\w | Kapitel gefolgt von genau einem Leerraum-Zeichen (Leerzeichen, Tabulator, neue Zeile, usw.), gefolgt von genau einem Wort-Zeichen (siehe XML 1.0 Buchstabe oder Ziffer) |
Espanñola | Española |
\p{Lu} | Irgendein Großbuchstabe; der Wert von \p{} (d.h. "Lu") wird in Unicode definiert |
\p{IsGreek} | Irgendein griechischer Buchstabe; das 'Is' Konstrukt kann für jeden der von Unicode definierten Blöcke (so wie “Greek”) verwendet werden |
\P{IsGreek} | Irgendein nicht-griechischer Buchstabe; das 'Is' Konstrukt kann für jeden der von Unicode definierten Blöcke (so wie “Greek”) verwendet werden |
a*x | x, ax, aax, aaax .... |
a?x | ax, x |
a+x | ax, aax, aaax .... |
(a|b)+x | ax, bx, aax, abx, bax, bbx, aaax, aabx, abax, abbx, baax, babx, bbax, bbbx, aaaax .... |
[abcde]x | ax, bx, cx, dx, ex |
[a-e]x | ax, bx, cx, dx, ex |
[-ae]x | -x, ax, ex |
[ae-]x | ax, ex, -x |
[^0-9]x | Irgendein Zeichen, das keine Ziffer ist, gefolgt von einem x |
\Dx | Irgendein Zeichen, das keine Ziffer ist, gefolgt von einem x |
.x | Irgendein Zeichen, gefolgt von einem x |
.*abc.* | 1x2abc, abc1x2, z3456abchooray .... |
ab{2}x | abbx |
ab{2,4}x | abbx, abbbx, abbbbx |
ab{2,}x | abbx, abbbx, abbbbx .... |
(ab){2}x | ababx |
XML Schema Elemente. Jeder Element-Name ist mit seiner formalen XML-Beschreibung entweder im Struktur- oder im Datentypenteil der XML Schema Spezifikation verlinkt. Neben dem Elementnamen stehen, durch ihre Kapitelnummer gekennzeichnet, ein oder mehrere Verweise auf Beispiele in dieser Einführung.
restriction
: 2.3, 4.4
XML Schema Attribute. Zu jedem Attribut-Namen ist mindestens ein Paar von Referenzen angegeben. Es besteht aus einer Verknüpfung mit einem Beispiel aus dieser Einführung und einem Verweis auf die formale XML-Beschreibung, entweder im Struktur- oder im Datentypen-Teil der XML Schema Spezifikation.
abstract
: Element-Deklaration [
Struktur], complexType-Definition [
Struktur]
attributeFormDefault
:
schema
-Element [
Struktur]
base
: simpleType-Definition [
Datentypen], complexType-Definition [
Struktur]
block
: complexType-Definition [ Struktur]
blockDefault
:
schema
-Element [
Struktur]
default
:
Attribut-Deklaration [
Struktur]
default
:
Element-Deklaration [
Struktur]
elementFormDefault
:
schema
-Element [
Struktur]
final
: complexType-Definition [
Struktur]
finalDefault
:
schema
-Element [
Struktur]
fixed
:
Attribut-Deklaration [
Struktur]
fixed
: Element-Deklaration [
Struktur]
fixed
:
simpleType-Definition [
Datentypen]
form
: Element-Deklaration [
Struktur], Attribut-Deklaration [
Struktur]
itemType
:
Listentyp-Definition [
Datentypen]
memberTypes
: Vereinigungstyp-Definition [
Datentypen]
maxOccurs
: Element-Deklaration
[
Struktur]
minOccurs
: Element-Deklaration
[
Struktur]
mixed
:
complexType-Definition [
Struktur]
name
: Element-Deklaration [
Struktur], Attribut-Deklaration [
Struktur], complexType-Definition [
Struktur], simpleType-Definition [
Datentypen]
namespace
:
any
-Element [
Struktur],
include
-Element [
Struktur]
noNamespaceSchemaLocation
:
instance
-Element [
Struktur]
xsi:nil
:
instance
Element [
Struktur]
nillable
:
Element-Deklaration [
Struktur]
processContents
:
any
-Element [
Struktur],
anyAttribute
-Element [
Struktur]
ref
: Element-Deklaration [
Struktur]
schemaLocation
: Include-Spezifikation [
Struktur], Redefine-Spezifikation [
Struktur], Import-Spezifikation [
Struktur]
xsi:schemaLocation
: Instanz
Attribut [
Struktur]
substitutionGroup
: Element-Deklaration [
Struktur]
targetNamespace
:
schema
-Element [
Struktur]
type
: Element-Deklaration [
Struktur], Attribut
Declaration [
Struktur]
xsi:type
:
instance
-Element [
Struktur]
use
: Attribut-Deklaration [
Struktur]
xpath
:
selector
- & field
-Elemente [
Struktur]
Einfache Typen werden in Tabelle 2 beschrieben.