XML Schema und Anwendungen

Seminarvortrag von Serdar Sütlüce

  1. Einführung
  2. Elemente
  3. Attribute
  4. Datentypen
  5. Namensräume

1. Einführung

Spätestens mit der Nutzung von XML als Datenbeschreibungsformat wurde deutlich, dass die Möglichkeiten einer DTD nicht ausreichend ist. Mit Hilfe einer DTD können zwar Dokumentstrukturen beschrieben werden aber nicht die vollständige Datenmodelle. keine Unterstützung von Namensräumen.

Um dieses Problem zu Überwinden wurden eine ganze Reihe von Schema-Sprachen entwickelt.
Zu zählen sind:

Vorteile von XML Schema sind:

Anstatt eine .dtd Datei beschreibt beim XML-Schema eine .xsd Datei. Diese Beschreibung wird anhand der unten aufgeführten Komponenten vorgenommen. Das heißt die .xsd Datei besteht aus Kombinationen dieser 12 verschiedenen vordefinierten Komponenten.
Die primären Komponenten umfassen die Mechanismen zur Definiton von Elementen / Attributen und eigener Datentypen. Die sekundären Komponenten dienen hauptsächlich zum Zusammenfassen von primären Komponenten. Die Hilfskomponenten sind meist Bestandteile anderer Komponenten. So kommen Annotationen (Bemerkungen zu Komponenten) in einem "gut beschriebenen Quellcode" immer vor:

Primäre Komponenten

Sekundäre Komponenten

Hilfskomponenten

Jedes Schema ist ein XML-Dokument (XML konform). Es muss keine neue Syntax erlernt (wie bei der DTD) und Schemata können durch jeden XML.Parser verarbeitet werden.

Grundgerüst eines Schemas:
Dateiendung: .xsd (extensible schema definition)

     <?xml version=„1.0“ encoding=„UTF-8“?>
        <schema xmlns:xsd=„http://www.w3c.org/2001/xmlSchema“>
           ...hier folgt die Dokumentbeschreibung...
        </schema>

Alle Schemata haben "schema" als Rootelement.
Die Elemente und Datentypen kommen aus http://www.w3c.org/2001/xmlSchema (default Namensraum)

2. Elemente

top
1.Elemente müssen einen Namen und einen Datentyp als Attribute besitzen.

Elementdeklaration aus W3C-Spezifikation

     <element>
        abstract = boolean : false
        block = (#all | List of (extension | restriction | substitution))
        default = string
        final = (#all | List of (extension | restriction))
        fixed = string
        form = (qualified | unqualified)
        id = ID
        maxOccurs = (nonNegativeInteger | unbounded) : 1
        minOccurs = nonNegativeInteger : 1
        name = NCName
        nillable = boolean : false
        ref = QName
        substitutionGroup = QName
        type = QName
        {any attributes with non-schema namespace . . .}>
        Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
     </element>
Eine Elementdeklaration wird also von <element> </element> tags eingeschlossen. Als Inhalt können Elemente annotation, simpleType, complexType oder Identity Constraints enthalten.
* minOccurs gibt an  die Minimumanzahl des Auftretens
        – nonNegativeInteger
        – defaults 1
* maxOccurs gibt an die maximum Anzahl des Auftretens
        – nonNegativeInteger oder unbeschränkt
        – defaults  1
Deklaration von Elementen in XML-Schema:
     <?xml version = "1.0" encoding = "UTF-8"?>
       <xsd:schema xmlns:xsd = "http://www.w3.org/2001/XMLSchema">
          <xsd:element name=”Vorname” type=”xsd:string”/>
       </xsd:schema>
zugehörige DTD:
     DTD:
     <!ELEMENT Vorname (#PCDATA)>
2. Elemente können bezüglich ihrer Kardinalität definiert werden
     <xsd:element name="Rechnungsadresse" minOccurs="0"  maxOccurs="unbounded"/>
       <xsd:complexType>
         <xsd:sequence>
           <xsd:element name="name"    type="xsd:string"/>
           <xsd:element name="strasse" type="xsd:string"/>
           <xsdelement  name="plz"     type="xsd:decimal"/>
           <xsd:element name="stadt"   type="xsd:string"/>
           <xsd:element name="land"    type="xsd:string"/>
        <xsd:sequence>
       <xsd:complexType>
     <xsd:element>
zugehörige DTD:
DTD:
    <!ELEMENT Rechnungsadresse (name+, strasse+, plz+, stadt+, land+)*>
3. Der Datentyp eines Elements kann als Simple Type oder Complex Type definiert werden

Simple Typ:

SimpleType Definitionen erweitern lediglich einen vorhanden Basistyp. Der neue Datentyp entsteht durch Anwenden der Operatoren list, union oder restriction auf den Basistyp. Wie die Namen der Operatoren schon andeuten entsteht der neue Datentyp durch erstellen einer Liste, Einschränkung oder Vereinigung.

     <simpleType
        final = (#all | (list | union | restriction))
        id = ID
        name = NCName
        {any attributes with non-schema namespace . . .}>
        Content: (annotation?, (restriction | list | union))
      <simpleType>
Complex Typ:

Im Gegensatz zu den simpleType Definitionen bestehen complexType Datentypen aus mehreren Elementen oder Attributen. Diese Elemente sind nach XML-Spezifikation vom Typ simple oder complexContent und können durch Anwendung der Model Group Operatoren all, choice und sequence geeignet kombiniert werden.

        <complexType
                abstract = boolean : false
                block = (#all | List of (extension | restriction))
                final = (#all | List of (extension | restriction))
                id = ID
                mixed = boolean : false
                name = NCName
                {any attributes with non-schema namespace . . .}>
                Content: (annotation?, (simpleContent | complexContent | ((group | all | choice |
                sequence)?, ((attribute | attributeGroup)*, anyAttribute?))))
        </complexType>
        sequence: alle aufgeführten Elemente müssen im XML-Dokument in der genannten Reihenfolge erscheinen
        all:      alle aufgeführten Elemente müssen im XML-Dokument erscheinen, die Reihenfolge ist beliebig
        choice:   genau eines der Elemente muss im XML-Dokument verwendet werden
        group:    zur Bildung einer Element-Gruppe, auf die an anderer Stelle im XML-Schema verwiesen werden kann
       <xsd:element name="leben">
        <xsd:complexType>
            <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                    <xsd:element name="arbeiten" type="xsd:string"/>
                    <xsd:element name="essen" type="xsd:string"/>
                </xsd:sequence>
                <xsd:choice>
                    <xsd:element name="arbeiten" type="xsd:string"/>
                    <xsd:element name="spielen" type="xsd:string"/>
                </xsd:choice>
                <xsd:element name="schlafen" type="xsd:string"/>
             </xsd:sequence>
          </xsd:complexType>
      </xsd:element>

      DTD:
      <!ELEMENT life ((arbeiten, essen)*, (arbeiten | spielen), schlafen)* >
        <xsd:element name="Buch"  maxOccurs="unbounded">
          <xsd:complexType>
            <xsd:all>
                <xsd:element name="Titel" type="xsd:string"/>
                <xsd:element name="Author" type="xsd:string"/>
                <xsd:element name="Datum" type="xsd:date"/>
                <xsd:element name="ISBN" type="xsd:string"/>
                <xsd:element name="Verlag" type="xsd:string"/>
            </xsd:all>
          </xsd:complexType>
        </xsd:element>
Das Element Buch hat mehrere Unterelemente, sie müssen in einem Dokument alle vorkommen, aber dürfen in der belibigen Reihenfolge erscheinen.

3. Attribute

top
Attribute erscheinen innerhalb einer Elementdeklaration am Schluss.
       <attribute
        default = string
        fixed = string
        form = (qualified | unqualified)
        id = ID
        name = NCName
        ref = QName
        type = QName
        use = (optional | prohibited | required) : optional
        {any attributes with non-schema namespace . . .}>
        Content: (annotation?, (simpleType?))
       </attribute>

Attribute werden für Daten benutzt, die Hintergrundinformationen darstellen und für Benutzer nicht optisch erscheinen sollen (Beispiel hierfür ist bei Bildern in HTML-Seiten die Angabe der Quelle).

Attribute können auch innerhalb eines Elements neu definiert werden. Jedes Attribut darf in einem Element nur einmal definiert werden, kann in anderen Elementen aber wieder benutzt werden.

     <attribute name="name" type="simple-type" use="wie es benutzt wird" default/fixed="value"/>
Mit form kann man anhand qualified /unqualified bestimmen, ob bei Benutzung des Attributes der Aufruf den vollständigen Pfad oder nur den Attributnamen beinhalten muß.
          use=
          "optional": das Attribut darf angegeben werden
          "required": das Attribut muss angegeben werden
          "prohibited"  : das Attribut darf nicht benutzt werden
        
          Auftreten:
          * : nullmal oder öfter
          + : einmal oder öfter
          kein Zeichen: einmaliges Vorkommen
        
        <element name="datalist" minOccurs="1">
        ...
        <attribute name="ergebnis" use="required" type="string"/>
        ...
        </element>

        DTD:
        <!ATTLIST datalist ergebnis CDATA #REQUIRED>

4.Datentypen

top
Ein Datentyp ist nach W3C Spezifikation ein 3-Tupel mit den Bestandteilen value space, lexical space und facets.

Datentyp Hierarchie

Aufgrund der unterschiedlichen Eigenschaften aller Datentypen lassen sie sich in mehrere Kategorien aufteilen. Das W3C stellt davon 3 Klassifizierungen heraus: atomic versus list versus union

Alle Datentypen lassen sich in die 3 Bereiche atomic, list und union aufteilen.

Aufbau eines Datentyps

Wie am Anfang schon erwähnt ist ein Datentyp ein 3-Tupel bestehend aus folgenden Elementen:

value space

Der value space bezeichnet eine abstrakte Sammlung von Werten die dieser Datentyp aufnehmen kann (z.B: integer, float, boolean etc).Der value space (oder Wertemenge) eines bestimmten Datentyps kann auf eine der folgenden Arten definiert werden:

lexical space

Als "lexical space" bezeichnet man die Menge der gültigen Literale für einen bestimmten Datentyp. Beispiel: "100" und "1.0E2" sind zwei verschiedene Literale aus dem "lexical space" des Datentyp float, aber beide repräsentieren den selben Wert.

Facets

Facetten charakterisieren die Eigenschaften des value space eines Datentyp. Man unterscheidet dabei zwischen fundamentalen, welche grundlegende Eigenschaften definieren, und constraining Facetten, welche den value space "nur" einschränken. Zu den fundamentalen Facetten gehören:

Die „constraining“ Facetten können optional angewandt werden. Wie wir aber sehen werden, sind sie sehr nützlich, um aus schon vorhandenen Datentypen, neue speziellere Datentypen zu generieren.

Built in Datentypen

Diese Typen sind schon in der XML-Schema Spezifikation enthalten. Man unterscheidet sie jedoch in primitive "built in" und abgeleitete "built in" Typen.
Die primitiven Datentypen bilden die Basis für die abgeleiteten Datentypen.
Die komplette Liste zu abgeleiteten Datentypen ist auf der Site von W3C zu sehen.

Annotation

dienen zur Dokumentation eines XML-Schemata. So können mit dem <annotation> tag Kommentare in Attribut - , Element-, ComplexType- Deklarationen etc. eingefügt werden und führen so zu einem besseren Verständnis des Schemata. Annotationen sollten direkt dem Starttag des zu kommentierenden Elements folgen. Die Syntax ist:

        <annotation
             id = ID
             {any attributes with non-schema namespace . . .}>
             Content: (appinfo | documentation)*
        </annotation>
documentation sorgt Kommentare für Menschen und
appinfo übermitellet die Informationen für die Programme, die das XML-Dokument verarbeiten
Für die Valiedierung haben Annotationen keinen Effekt.
        <xsd:element name="Author" type="xsd:string"/>
        <xsd:element name="Date" type="xsd:string">
           <xsd:annotation>
              <xsd:documentation>z.B. Copytight informationen </xsd:documentation>
              <appInfo>Vielleicht letzte Änderungsdaten für Roboter</appInfo>
            </xsd:annotation>
        </xsd:element>

Attribute Group Definiton

Durch Anwendung der Group-Definition hat der Benutzer die Möglichkeit mehrere (meist von der Funktion her verwandte) Attribute zu einer Gruppe zusammenzufassen, um sie immer wieder verwenden zu können.Beispiel

Model Group Definiton

Anhand einer Model Group Definition können mehrere Elemente zu einer Gruppe zusammengefaßt werden. Attribute sind in so einer Deklaration nicht erlaubt.Beispiel

Wildcard

Eine Wildcard hat das any Element als Komponente. Damit kann in eine XML-Schema- Instanz an ausgewiesenen Stellen beliebiger wohlgeformter XML Code eingefügt werden. Dabei kann festgelegt werden, wie der Schemaprozessor mit dem „fremden“ Code umgehen soll: strict um den Code validieren zu müssen, lax um zu validieren soviel geht und skip um die Validierung zu umgehen. Im namespace Attribute wird festgelegt, wo der eingefügte Code herstammt, um eventuell validieren zu können. Die Syntax des any Elements sieht folgendermaßen aus:

        <any
                id = ID
                maxOccurs = (nonNegativeInteger | unbounded) : 1
                minOccurs = nonNegativeInteger : 1
                namespace = ((##any | ##other) | List of (uriReference | (##targetNamespace | ##local)) ) : ##any
                processContents = (skip | lax | strict) : strict
                {any attributes with non-schema namespace . . .}>
                Content: (annotation?)
        <:/any>
Man könnte beispielsweise im BookCatalogue ein Review Element hinzufügen, an dem dann beliebige Elemente eingefügt werden können.
       <element name="Review">
          <complexType>
           <sequence>
             <any namespace="##local" minOccurs="0" maxOccurs="unbounded"/>
           </sequence>
          </complexType>
        </element>
Dann wäre z.B. folgendes in einem Instanzobjekt denkbar:
        <Review>
          <Reviewer xmlns="">Roger L. Costello</Reviewer>
          <Comments xmlns="">A great book, especially if you're a Beatle's fan.</Comments>
        </Review>

Identity Constraints

Da XML-Schema keine Einschränkung gegenüber der DTD haben soll, fehlt bis jetzt noch die Möglichkeit um Elemente eindeutig zu halten, wie es mit dem ID und IDREF Attributen der DTD möglich war. XML-Schema bietet hierfür die Identity Constraint Komponenten unique, key und keyref.

Der Unterschied zwischen key und unique besteht darin, dass das mit key spezifizierte Element vorkommen muss und eindeutig ist, unique besagt, dass das Element, falls es vorkommt, eindeutig sein muss. Keyref entspricht im wesentlichen IDREF, wobei festgelegt wird, dass die Elemente den Werten entsprechen müssen, die durch keyref referenziert werden. Im Beispiel wäre etwa die ISBN ein Wert der eindeutig sein muss. Das lässt sich wie folgt festlegen: Nach der Complex Type Definition von „Book“ in BookCatalogue.xsd einfach einen Schlüssel definieren.

        <key name="AB">
          <selector xpath="Book"/>
          <field xpath="ISBN"/>
        </key>
Es wird also im BookCatalogue ein Schlüssel AB definiert der mit selector eine Menge von Elementen spezifiziert (hier Book) auf die der Schlüssel angewendet wird und field gibt an aus welchen Elementen der Schlüssel besteht (hier nur ISBN, es können aber auch mehrere field Elemente zusammengesetzte Schlüssel bilden). Es könnte nun auch noch einen Author geben, der Bücher signiert, allerdings nur Bestimmte. Das kann man dann mit einem keyref erreichen:
        <keyref name="isbnRef" refer="cat:PK">
           <selector xpath="GuestAuthors/Author/BookForSigning"/>
           <field xpath="ISBN"/>
        </keyref>
Key, Unique und Keyref können an beliebigen Stellen im Schema definiert werden, dadurch kann man bestimmen in welchem Bereich die Schlüssel ihre Gültigkeit haben.

complexContent / simpleContent

With complexContent you extend or restrict a complexType mit complexContent kann mann einen complexType einschränken oder erweitern.

    <xsd:complexType name="Publication">
        <xsd:sequence>
            <xsd:element name="Title" type="xsd:string" maxOccurs="unbounded"/>
            <xsd:element name="Author" type="xsd:string" maxOccurs="unbounded"/>
            <xsd:element name="Date" type="xsd:gYear"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="BookPublication">
        <xsd:complexContent>
            <xsd:extension base="Publication" >
                <xsd:sequence>
                    <xsd:element name="ISBN" type="xsd:string"/>
                    <xsd:element name="Publisher" type="xsd:string"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
    <xsd:element name="Book" type="BookPublication"/>
Hier erweitert der complexType BookPublication den complexType Publication um ISBN und Publisher.
<xsd:complexType name="Publication">
        <xsd:sequence>
                <xsd:element name="Title" type="xsd:string" maxOccurs="unbounded"/>
                <xsd:element name="Author" type="xsd:string" maxOccurs="unbounded"/>
                <xsd:element name="Date" type="xsd:gYear"/>
        </xsd:sequence>
</xsd:complexType>
<xsd:complexType name= "SingleAuthorPublication">
    <xsd:complexContent>
        <xsd:restriction base="Publication">
            <xsd:sequence>
                <xsd:element name="Title" type="xsd:string" maxOccurs="unbounded"/>
                <xsd:element name="Author" type="xsd:string"/>
                <xsd:element name="Date" type="xsd:gYear"/>
            </xsd:sequence>
        </xsd:restriction>
    </xsd:complexContent>
</xsd:complexType>
der complexType Publication wird im complexType SingleAuthorPublication eingeschränkt. Das Element Author darf jetzt genau einmal auftreten.
        <xsd:element name="apple">
            <xsd:complexType>
                <xsd:simpleContent>
                    <xsd:extension base="xsd:string">
                        <xsd:attribute name="variety" type="xsd:string" use="required"/>
                    </xsd:extension>
                </xsd:simpleContent>
            </xsd:complexType>
        </xsd:element>

        XML Dokument:
        <apple variety="Cortland">Large, green, sour</apple>

5. Namensräume

top
Der Mechanismus der Namespaces wurde nötig, da nun in XML-Schemata Ressourcen aus mehreren schon existierenden DTD´s / XML-Schemata parallel wiederverwendet werden können. Dies würde ohne Einsatz eines Konzeptes wie die Namespaces zu Mehrdeutigkeiten oder Kollisionen zwischen Variablennamen oder Elementtypen führen. Einfach gesagt ist ein XML-Namespace eine Menge von Namen die über eine URI (Uniform Resource Identifier) eindeutig identifiziert werden können und in XML - Dokumenten als Elementtypen oder Variablennamen verwendet werden. (import ermöglicht den Zugang zu den Elementen und Typen, die in verschiedenen Namensräumen definiert sind. die Kamerainstanz benutzt Element von Nikon, Olympus, and Pentax namespaces)
(Ein Schema kann <include> ein anderes Schema.)

Links zu XML Schema

W3C Consortium XML Schema
Xmlschema.com
xFront.com ( Nüzliche Seite mit Tutorials )