Komplexe Inhaltsmodelle

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

Einfache Inhaltsmodelle einzuschränken oder zu erweitern ist zwar praktisch, jedoch ist XML ohne komplexere Modelle nicht sehr nützlich.

Erzeugung komplexer Inhalte

Komplexe Inhalte werden erzeugt, indem man die Liste (und die Reihenfolge) ihrer Elemente und Attribute festlegt. Wir haben bereits einige Beispiele für komplexe Inhaltsmodelle gesehen, die unter Verwendung und Entwicklung von Schemas und Unser erstes Schema als lokale komplexe Typen definiert worden sind:

<xs:element name="library">
  <xs:complexType>
    <xs:sequence>
       <xs:element ref="book" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>


<xs:element name="author">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="name"/>
      <xs:element ref="born"/>
      <xs:element ref="dead" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute ref="id"/>
  </xs:complexType>
</xs:element>

Diese Beispiele zeigen die Grundstruktur der Definition eines komplexen Typs mit komplexem Inhalt: Das Element xs:complexType enthält die Definition. Hier ist diese Definition lokal (xs:complexType steht nicht auf der obersten Ebene, da es in einem Element xs:element enthalten ist) und daher anonym. Unterhalb von xs:complexType finden wir die Folge der Kindelemente (xs:sequence) und die Liste der Attribute.

Kompositoren und Partikeln

In diesen Beispielen übernehmen die xs:sequence-Elemente eine Rolle als »Kompositoren«, während die xs:element-Elemente, die innerhalb von xs:sequence stehen, eine Rolle als »Partikeln« spielen. Dieses einfache Drehbuch kann erweitert werden, indem man andere Kompositoren und Partikeln verwendet.

W3C XML Schema definiert drei verschiedene Kompositoren: xs:sequence zur Definition geordneter Listen von Partikeln, xs:choice zur Definition einer Auswahl einer Partikel aus mehreren und xs:all zur Definition einer ungeordneten Liste von Partikeln. Die Kompositoren xs:sequence und xs:choice können mit den Attributen minOccurs und maxOccurs selbst die Häufigkeit des Auftretens festlegen, und sie können als Partikeln verwendet werden. (Für xs:all, das nicht als Partikel verwendet werden kann, wie wir im nächsten Abschnitt sehen werden, gelten einige bedeutsame Einschränkungen.)

Die Partikeln sind xs:element, xs:sequence, xs:choice und zusätzlich xs:any und xs:group, denen wir später in diesem Abschnitt begegnen werden. Die Fähigkeit, Kompositoren innerhalb von Kompositoren zu verwenden, ist der Schlüssel zur Definition komplexer Strukturen, auch wenn sie unseligerweise an der Allergie von W3C XML Schema gegen »Nicht-Determinismus« leidet.

Um eine Vorstellung von der Art der Strukturen, die definiert werden können, zu geben, nehmen wir an, daß die Namen in unserer Bibliothek auf zwei verschiedene Arten ausgedrückt werden dürfen: entweder als Element name, wie wir es bisher gezeigt haben, oder als drei getrennte Elemente, um den Vornamen, einen zweiten Vornamen (der optional sein sollte) und den Nachnamen anzugeben. Namen könnten dann auf eine der drei folgenden Kombinationen geschrieben werden:

<first-name>
Charles
</first-name>
<middle-name>
M.
</middle-name>
<last-name>
Schulz
</last-name>
<first-name>

oder:

<first-name>
Peppermint
</first-name>
<last-name>
Patty
</last-name>

oder:

<name>
Snoopy
</name>

Um dies zu beschreiben, ersetzen wir den Verweis auf das Element name mit einer Auswahl zwischen einem Element name oder aber einer Folge von first-name, middle-name (optional) und last-name. Die Definition von author sieht dann wie folgt aus:

<xs:element name="author">
  <xs:complexType>
    <xs:sequence>
       <xs:choice>
          <xs:element ref="name"/>
          <xs:sequence>
             <xs:element ref="first-name"/>
             <xs:element ref="middle-name" minOccurs="0"/>
             <xs:element ref="last-name"/>
          </xs:sequence>
       </xs:choice>
       <xs:element ref="born"/>
       <xs:element ref="dead" minOccurs="0"/>
    </xs:sequence>
   <xs:attribute ref="id"/>
 </xs:complexType>
</xs:element>

Das Element name erscheint auch in dem Element character. Mit Kopieren/Einfügen kann es dort ebenfalls durch die xs:choice-Struktur ersetzt werden, aber wir würden lieber die Gelegenheit ergreifen, eine neue Konstruktion einzuführen, die für die Handhabung wiederverwendbarer Mengen von Elementen sehr praktisch ist.

Element- und Attributgruppen

Element- und Attribut gruppen sind Container, in die eine Reihe von Elementen bzw. Attributen eingebettet werden kann. Die Container können als Ganzes verarbeitet werden. Diese einfachen und flexiblen Strukturen sind sehr praktisch, wenn man Stücke von Inhaltsmodellen definieren will, die an mehreren Stellen wiederverwendet werden können. Dies bietet sich beispielsweise für die xs:choice-Struktur an, die wir für unseren Namen erzeugt haben.

Der erste Schritt besteht darin, die Elementgruppe festzulegen. Die Definition muß benannt und global (d.h. unmittelbar unter dem Element xs:schema angesiedelt) sein. Der Aufbau ist wie folgt:

   <xs:group name="name">
      <xs:choice>
         <xs:element ref="name"/>
         <xs:sequence>
            <xs:element ref="first-name"/>
            <xs:element ref="middle-name" minOccurs="0"/>
            <xs:element ref="last-name"/>
         </xs:sequence>
      </xs:choice>
   </xs:group>     
     

Solche Gruppen können dann durch Verweise als Partikeln innerhalb von Kompositoren verwendet werden:

   <xs:element name="author">
      <xs:complexType>
         <xs:sequence>
            <xs:group ref="name"/>
            <xs:element ref="born"/>
            <xs:element ref="dead" minOccurs="0"/>
         </xs:sequence>
         <xs:attribute ref="id"/>
      </xs:complexType>
   </xs:element>


   <xs:element name="character">
      <xs:complexType>
         <xs:sequence>
            <xs:group ref="name"/>
            <xs:element ref="born"/>
            <xs:element ref="qualification"/>
         </xs:sequence>
         <xs:attribute ref="id"/>
      </xs:complexType>
   </xs:element>

Gruppen von Attributen können auf gleiche Weise unter Verwendung von xs:attributeGroup erzeugt werden:

<xs:attributeGroup name="bookAttributes">
      <xs:attribute name="id" type="xs:ID"/>
      <xs:attribute name="available" type="xs:boolean"/>
   </xs:attributeGroup>
   <xs:element name="book">
      <xs:complexType>
         <xs:sequence>
            <xs:element ref="isbn"/>
            <xs:element ref="title"/>
            <xs:element ref="author" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element ref="character" minOccurs="0"
               maxOccurs="unbounded"/>
         </xs:sequence>
         <xs:attributeGroup ref="bookAttributes"/>
      </xs:complexType>
   </xs:element>

Die UPA-Regel (»Unique Particle Attribution Rule«): Eindeutige Partikelzuordnung

Probieren wir ein weiteres Beispiel aus, das eine der strengsten Begrenzungen von W3C XML Schema illustriert. Wir möchten sämtliche Seiten unserer Bücher beschreiben und wollen dabei unterschiedliche Beschreibungen unter Verwendung verschiedener Elemente benutzen, etwa odd-page und even-page für die ungeraden bzw. die geraden Seiten, die jeweils unterschiedlich paginiert werden müssen. Wir können versuchen, das neue Inhaltsmodell mit der folgenden Gruppe zu beschreiben:

<xs:group name="pages">
   <xs:sequence>
      <xs:sequence minOccurs="0" maxOccurs="unbounded">
         <xs:element ref="odd-page"/>
         <xs:element ref="even-page"/>
      </xs:sequence>
      <xs:element ref="odd-page" minOccurs="0"/>
   </xs:sequence>
</xs:group>

Dies sieht nach einer einfachen, cleveren Methode aus, die Abfolge ungerader und gerader Seiten zu beschreiben: eine Reihe ungerader und gerader Seiten, an deren Ende möglicherweise eine letzte ungerade Seite steht. Das Modell deckt sowohl Bücher mit geraden und ungeraden Seitenzahlen als auch Minibroschüren ab, die aus einer einzigen Seite bestehen. Jedoch wissen das anscheinend weder XSV noch Xerces zu würdigen:

XSV:

vdv@evlist:~/w3c-xml-schema/user/examples/complex-types$ xsd -n first-ambigous.xsd first-ambigous.xml
using xsv (default)
<?xml version='1.0'?>
<xsv docElt='{None}library' instanceAssessed='true' instanceErrors='0'
rootType='[Anonymous]' schemaDocs='first-ambigous.xsd' schemaErrors='1'
target='/home/vdv/w3c-xml-schema/user/examples/complex-types/first-ambigous.xml'
validation='strict' version='XSV 1.203.2.20/1.106.2.11 of 2001/11/01 17:07:43'
xmlns='http://www.w3.org/2000/05/xsv'>
<schemaDocAttempt URI='/home/vdv/w3c-xml-schema/user/examples/complex-types/first-ambigous.xsd'
outcome='success' source='command line'/>
<schemaError char='7' line='65' phase='instance'
resource='file:///home/vdv/w3c-xml-schema/user/examples/complex-types/first-ambigous.xsd'>
non-deterministic content model for type None: {None}:odd-page/{None}:odd-page</schemaError>
</xsv>

Xerces:

   vdv@evlist:~/w3c-xml-schema/user/examples/complex-types$ xsd -n first-ambigous.xsd
   -p xerces-cvs first-ambigous.xml
   using xerces-cvs
   startDocument
   [Error] first-ambigous.xml:2:10: Error: cos-nonambig: (,odd-page)
   and (,odd-page) violate the "Unique Particle Attribution" rule.
   endDocument

Verführt durch die Flexibilität der Konstruktionen mit Kompositoren und Partikeln haben wir ein uraltes Tabu gebrochen, das bei SGML als »mehrdeutige Inhaltsmodelle« bekannt ist. Unter dem Namen »nicht-deterministische Inhaltsmodelle« wurde es in die DTDs von XML importiert, und W3C XML Schema behält es als »Unique Particle Attribution Rule«, die Regel von der eindeutigen Partikelzuordnung (UPA-Regel), bei.

In der Praxis macht diese Regel das Schreiben eines W3C XML Schemas erheblich komplizierter, denn sie muß erfüllt werden, nachdem all die verschiedenen Möglichkeiten, mit denen man komplexe Typen definieren, umdefinieren, ableiten, importieren, referenzieren und ersetzen kann, vom Schema-Prozessor verarbeitet worden sind. Die Schema-Empfehlung erkennt an, daß »angesichts von Elementersetzungsgruppen und Wildcards die knappe Beschreibung dieser Einschränkung schwierig ist«. Nach der Verarbeitung der genannten Konstruktionen bleibt am Ende die Anforderung, daß ein Schema-Prozessor bei der Validierung eines Elements niemals im Zweifel darüber sein darf, in welchem Zweig der Definition er sich gerade befindet – und zwar auch dann, wenn er nur dieses eine Element betrachtet. Angewendet auf das vorige Beispiel, das so einfach wie möglich gebaut war,wird das Problem klar: Wenn ein Schema-Prozessor auf das erste odd-page-Element trifft, kann er nicht wissen, ob der Seite ein even-page-Element folgen wird, ohne zunächst das nächste Element vorab anzusehen. Dies ist eine Verletzung der Regel von der eindeutigen Partikelzuordnung.

Dieses Beispiel, das eine angepaßte Form eines Beispiels zur Beschreibung eines Schachbretts ist, ist einer der berühmten Fälle, in denen das Inhaltsmodell nicht auf »deterministische« Weise beschrieben werden kann. Das ist nicht immer der Fall, denn viele nicht-deterministische Konstruktionen beschreiben Inhaltsmodelle, die sich auf deterministische Art neu schreiben lassen. Wir sollten die wesentlich nicht-deterministischen und die nur »zufällig« nicht-deterministischen Fälle auseinanderhalten. Kehren wir zu unserem Beispiel mit der Namenssequenz zurück, die zwei verschiedene Inhaltsmodelle haben kann, und stellen wir uns vor, daß wir statt des Elementnamens first-name lieber erneut name verwenden wollen. Das Inhaltsmodell ist nun entweder name oder aber eine Folge von name, middle-name und last-name:

<xs:group name="name">
  <xs:choice>
    <xs:element ref="name"/>
    <xs:sequence>
       <xs:element ref="name"/>
       <xs:element ref="middle-name" minOccurs="0"/>
       <xs:element ref="last-name"/>
    </xs:sequence>
  </xs:choice>
</xs:group>

<xs:element name="author">
  <xs:complexType>
     <xs:sequence>
        <xs:group ref="name"/>
        <xs:element ref="born"/>
        <xs:element ref="dead" minOccurs="0"/>
     </xs:sequence>
     <xs:attribute ref="id"/>
   </xs:complexType>
</xs:element>

Wenn ein Prozessor auf ein Element namens name trifft, kann er auch hier (ohne vorauszuschauen) nicht wissen, ob dieses Element in den ersten oder aber in den zweiten Zweig der Auswahl gehört. In diesem Fall kann das Inhaltsmodell jedoch vereinfacht werden, wenn wir bemerken, daß das Element name beiden Zweigen gemeinsam ist und daß wir nun tatsächlich ein notwendiges Element name haben, dem wahlweise eine Folge aus einem seinerseits optionalen middle-name und einem notwendigen last-name folgen kann. Das Inhaltsmodell kann dann auf deterministische Weise geschrieben werden:

<xs:group name="name">
   <xs:sequence>
      <xs:element ref="name"/>
      <xs:sequence minOccurs="0">
         <xs:element ref="middle-name" minOccurs="0"/>
         <xs:element ref="last-name"/>
      </xs:sequence>
   </xs:sequence>
</xs:group>

Dies ist jedoch ein schlüpfriger Pfad, der oft von den Feinheiten des Inhaltsmodells abhängt. Dies führt zu Schemas, die schwer zu warten sind und manchmal wenig zufriedenstellende Kompromisse verlangen. Wenn sich die Anforderungen des Inhaltsmodells, das wir eben geschrieben haben, ändern und das name-Element in dem zweiten Zweig nicht mehr notwendig sein soll, stehen wir vor einem Problem. Das neue Inhaltsmodell sieht so aus:

<xs:group name="name">
  <xs:choice>
     <xs:element ref="name"/>
     <xs:sequence>
        <xs:element ref="name" minOccurs="0"/>
        <xs:element ref="middle-name" minOccurs="0"/>
        <xs:element ref="last-name"/>
     </xs:sequence>
  </xs:choice>
</xs:group>

Dieses Modell ist aus dem gleichen Grund wie das vorige nicht-deterministisch. Wenn wir nun die verschiedenen möglichen Kombinationen neu durchgehen, sehen wir, daß das neue Inhaltsmodell nun so ausgedrückt werden kann:

<xs:group name="name">
  <xs:choice>
     <xs:sequence>
        <xs:element ref="name"/>
        <xs:sequence minOccurs="0">
            <xs:element ref="middle-name" minOccurs="0"/>
            <xs:element ref="last-name"/>
        </xs:sequence>
      </xs:sequence>
      <xs:sequence>
        <xs:element ref="middle-name" minOccurs="0"/>
        <xs:element ref="last-name"/>
      </xs:sequence>
   </xs:choice>
</xs:group>

Formale Theorien und Algorithmen können nicht-deterministische Inhaltsmodelle auf deterministische Weise neu schreiben, wann immer das überhaupt möglich ist. Hoffentlich werden Entwicklungswerkzeuge für W3C XML Schema einige dieser Algorithmen aufgreifen, um eine Alternative vorzuschlagen, wenn ein Schema-Autor nicht-deterministische Inhaltsmodelle erzeugt.

Mehrdeutige Inhaltsmodelle waren bereits in den neunziger Jahren ein kontroverses Thema in der SGML-Gemeinschaft. Die Einschränkung ist in den DTDs von XML DTD unter dem Namen »nicht-deterministische Inhaltsmodelle« trotz der abweichenden Position von Tim Bray, Jean Paoli und Peter Sharpe beibehalten worden, drei einflußreichen Mitgliedern der XML Special Interest Group, die die Kompatibilität mit SGML-Parsern beibehalten wollte. Die Motivation dafür, die Einschränkung in W3C XML Schema aufrechtzuerhalten, besteht darin, einfach zu implementierende Schema-Prozessoren zu ermöglichen, beispielsweise auf der Grundlage endlicher Automaten (Finite State Machines, FSM). Die Ausführungszeit solcher Automaten kann exponentiell wachsen, wenn die UPA-Regel verletzt wird. Diese Entscheidung ist von Experten heftig kritisiert worden, darunter auch von Joe English, James Clark und Murata Makoto, die nachgewiesen haben, daß andere einfache Algorithmen verwendet werden könnten, die die Verarbeitungszeit linear halten, auch wenn die Regel nicht erfüllt wird. Dies ist auch einer der Hauptunterschiede zwischen den Beschreibungsmöglichkeiten von Schema-Sprachen wie RELAX, TREX und RELAX NG, die diese Regel nicht kennen, und W3C XML Schema.

Regel von der konsistenten Deklaration

Auch wenn sie strenggenommen nichts miteinander zu tun haben, werden die Regeln von der eindeutigen Partikelzuordnung und die Regel von der konsistenten Deklaration oft miteinander in Verbindung gebracht, denn in der Praxis wird oft auch die UPA-Regel verletzt, wenn keine konsistente Deklaration vorliegt. Diese neue Regel ist erheblich leichter zu erklären und zu verstehen, denn sie besagt lediglich, daß W3C XML Schema ausdrücklich die Auswahl zwischen Elementen gleichen Namens, aber verschiedenen Typs verbietet, wie es im folgenden Beispiel zu sehen ist:

<xs:choice>
  <xs:element name="name" type="xs:string"/>
  <xs:element name="name">
     <xs:complexType>
         <xs:sequence>
            <xs:element ref="first-name"/>
            <xs:element ref="middle-name"/>
            <xs:element ref="last-name"/>
         </xs:sequence>
     </xs:complexType>
  </xs:element>
</xs:choice>

Wir werden unter Referenz auf Schemas und Schema-Datentypen in XML-Dokumenten sehen, wie man dieses Problem mit Hilfe des Attributs xsi:type, das einige Anwendungen verwenden können, umgehen kann.

Beschränkungen für ungeordnete Inhaltsmodelle

Auch wenn sie nützlich sind, haben ungeordnete Inhaltsmodelle ihre eigenen Beschränkungen.

Beschränkungen von xs:all

Ungeordnete Inhaltsmodelle (d.h. Inhaltsmodelle, die ihren Kindelementen keine Reihenfolge auferlegen) erhöhen nicht nur die Gefahr nicht-deterministischer Inhaltsmodelle, sondern sind auch ein bedeutender Komplexitätsfaktor für Schema-Prozessoren. Um der einfacheren Implementierung willen erlegt die Recommendation dem Element xs:all schwerwiegende Beschränkungen auf, so daß es praktisch kaum brauchbar ist. xs:all kann nicht als Partikel verwendet werden, sondern nur als Kompositor; xs:all kann keine Auftretenshäufigkeit größer als eins haben; die Partikeln, die in xs:all enthalten sind, müssen alle vom Typ xs:element sein; außerdem dürfen diese Partikeln keine Auftretenshäufigkeiten größer als eins angeben.

Um diese Beschränkungen zu veranschaulichen, stellen wir uns einmal vor, wir hätten beschlossen, Schöpfern von Dokumenten das Leben leichter zu machen und ein Vokabular zu schaffen, bei dem es auf die Reihenfolge der Kindelemente nicht ankommt. Bei einem einfachen Vokabular wie dem, das wir in unserem ersten Schema definiert haben, würde das für eine Anwendung, die unser Vokabular behandelt, keine große Schwierigkeit bedeuten. Wenn Sie einmal darüber nachdenken, gibt es keinen besonderen Grund, daß der Titel eines Buchs erst nach seiner ISBN oder die Autorenliste vor der Liste der darin vorkommenden Personen stehen muß. Das erste Inhaltsmodell, das von dieser Entscheidung betroffen sein könnte, ist das des Elements book:

<xs:element name="book">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="isbn"/>
      <xs:element ref="title"/>
      <xs:element ref="author" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element ref="character" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute ref="id"/>
    <xs:attribute ref="available"/>
  </xs:complexType>
</xs:element>

Unglücklicherweise kann xs:sequence hier nicht durch xs:all ersetzt werden, da bei zweien der Kindelemente (author und character) die obere Grenze für die Häufigkeit des Auftretens »unbounded« und damit größer als eins ist. Die zweite Gruppe von Kandidaten besteht aus den Inhaltsmodellen von author und character, die ziemlich ähnlich aussehen:

   <xs:element name="author">
      <xs:complexType>
         <xs:sequence>
            <xs:element ref="name"/>
            <xs:element ref="born"/>
            <xs:element ref="dead" minOccurs="0"/>
         </xs:sequence>
         <xs:attribute ref="id"/>
      </xs:complexType>
   </xs:element>


   <xs:element name="character">
      <xs:complexType>
         <xs:sequence>
            <xs:element ref="name"/>
            <xs:element ref="born"/>
            <xs:element ref="qualification"/>
         </xs:sequence>
         <xs:attribute ref="id"/>
      </xs:complexType>
   </xs:element>
            
            

Hier haben wir die gute Nachricht, daß sowohl author als auch character die Kriterien für xs:all erfüllen, also können wir schreiben:

<xs:element name="author">
      <xs:complexType>
         <xs:all>
            <xs:element ref="name"/>
            <xs:element ref="born"/>
            <xs:element ref="dead" minOccurs="0"/>
         </xs:all>
         <xs:attribute ref="id"/>
      </xs:complexType>
   </xs:element>
   <xs:element name="character">
      <xs:complexType>
         <xs:all>
            <xs:element ref="name"/>
            <xs:element ref="born"/>
            <xs:element ref="qualification"/>
         </xs:all>
         <xs:attribute ref="id"/>
      </xs:complexType>
   </xs:element>

Wir können zwei Elemente (author und character) haben, bei denen die Reihenfolge der Kindelemente unerheblich ist. Man kann sich jedoch fragen, ob das wirklich spannend ist, denn diese Unabhängigkeit durchzieht nicht auf konsistente Art das ganze Schema. Noch wichtiger ist aber die Bemerkung, daß wir eine Menge an Flexibilität und Erweiterbarkeit verloren haben, wenn wir einen xs:all-Kompositor verwenden. Da die Maximalzahl für das Auftreten jedes Kindelements eins sein muß, können wir beispielsweise die Häufigkeit des Elements qualification nicht mehr ändern, so daß es mehrere Charakterisierungen in verschiedenen Sprachen aufnehmen könnte. Und da die in xs:all verwendeten Partikeln keine Kompositoren oder Gruppen sein dürfen, können wir das Inhaltsmodell auch nicht so erweitern, daß sowohl name als auch die Sequenz aus first-name, middle-name und last-name akzeptiert wird.

Da xs:all demnach im allgemeinen als ziemlich ineffektiv erscheint, gibt es einige Umgehungsstrategien, die sich für diejenigen eignen können, die ordnungsunabhängige Vokabulare entwickeln möchten.

Anpassen der Dokumentstruktur

Die erste Umgehungsstrategie, die Sie nur anwenden können, wenn Sie Ihr eigenes Vokabular von Grund auf entwickeln, besteht darin, die Strukturen in Ihrem Dokument an die Einschränkungen für xs:all anzupassen. In der Praxis läuft das darauf hinaus, daß wir jedes Mal, wenn wir xs:choice, xs:sequence oder Elemente mit einer Häufigkeit von mehr als eins verwenden müssen, ein neues Element als Container hinzufügen. Beispielsweise werden wir Container namens authors und characters anlegen, die die mehrfachen Nennungen von author bzw. character kapseln. Das Ergebnis sind Instanzdokumente wie das folgende:

 <?xml version="1.0"?>
   <library>
      <book id="b3810518883" available="true">
         <title lang="de">
            Auf den Hund gekommen
         </title>
         <isbn>
            3810518883
         </isbn>
         <authors>
            <author id="CMS">
               <born>
                  1922-11-26
               </born>
               <dead>
                  2000-02-12
               </dead>
               <name>
                  Charles M. Schulz
               </name>
            </author>
         </authors>
         <characters>
            <character id="PP">
               <name>
                  Peppermint Patty
               </name>
               <qualification>
                  kühn, dreist und draufgängerisch
               </qualification>
               <born>
                  1966-08-22
               </born>
            </character>
            <character id="Snoopy">
               <born>
                  1950-10-04
               </born>
               <name>
                  Snoopy
               </name>
               <qualification>
                  extrovertierter Beagle
               </qualification>
            </character>
            <character id="Schroeder">
               <qualification>
                  brachte die klassische Musik in die Peanuts-Comics ein
               </qualification>
               <name>
                  Schroeder
               </name>
               <born>
                  1951-05-30
               </born>
            </character>
            <character id="Lucy">
               <name>
                  Lucy
               </name>
               <born>
                  1952-03-03
               </born>
               <qualification>
                  herrschsüchtig, kratzbürstig und egoistisch
               </qualification>
            </character>
         </characters>
      </book>
   </library>
        
            
      

Dieses Instanzdokument würde durch ein komplettes Schema wie das folgende beschrieben:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="name" type="xs:token"/>
      <xs:element name="qualification" type="xs:token"/>
      <xs:element name="born" type="xs:date"/>
      <xs:element name="dead" type="xs:date"/>
      <xs:element name="isbn" type="xs:NMTOKEN"/>
      <xs:attribute name="id" type="xs:ID"/>
      <xs:attribute name="available" type="xs:boolean"/>
      <xs:attribute name="lang" type="xs:language"/>
      <xs:element name="title">
         <xs:complexType>
            <xs:simpleContent>
               <xs:extension base="xs:token">
                  <xs:attribute ref="lang"/>
               </xs:extension>
            </xs:simpleContent>
         </xs:complexType>
      </xs:element>
      <xs:element name="library">
         <xs:complexType>
            <xs:sequence>
               <xs:element ref="book" maxOccurs="unbounded"/>
            </xs:sequence>
         </xs:complexType>
      </xs:element>
      <xs:element name="authors">
         <xs:complexType>
            <xs:sequence>
               <xs:element ref="author" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
         </xs:complexType>
      </xs:element>
      <xs:element name="author">
         <xs:complexType>
            <xs:all>
               <xs:element ref="name"/>
               <xs:element ref="born"/>
               <xs:element ref="dead" minOccurs="0"/>
            </xs:all>
            <xs:attribute ref="id"/>
         </xs:complexType>
      </xs:element>
      <xs:element name="book">
         <xs:complexType>
            <xs:all>
               <xs:element ref="isbn"/>
               <xs:element ref="title"/>
               <xs:element ref="authors"/>
               <xs:element ref="characters"/>
            </xs:all>
            <xs:attribute ref="id"/>
            <xs:attribute ref="available"/>
         </xs:complexType>
      </xs:element>
      <xs:element name="characters">
         <xs:complexType>
            <xs:sequence>
               <xs:element ref="character" minOccurs="0"
                  maxOccurs="unbounded"/>
            </xs:sequence>
         </xs:complexType>
      </xs:element>
      <xs:element name="character">
         <xs:complexType>
            <xs:all>
               <xs:element ref="name"/>
               <xs:element ref="born"/>
               <xs:element ref="qualification"/>
            </xs:all>
            <xs:attribute ref="id"/>
         </xs:complexType>
      </xs:element>
   </xs:schema>
   

Eine solche Anpassung des Instanzdokuments wird schmerzlicher, wenn wir unser alternatives Inhaltsmodell für Namen implementieren wollen. Da wir kein xs:choice-Element in einem xs:all-Kompositor haben können, müssen wir eine erste Containerebene einfügen, die immer gleich bleibt, und dann eine zweite Container-Ebene, die nur die Auswahl enthält. Dies würde zu Instanzdokumenten wie dem folgenden führen:

 <?xml version="1.0"?>
   <library>
      <book id="b3810518883" available="true">
         <title lang="de">
            Auf den Hund gekommen
         </title>
         <isbn>
            3810518883
         </isbn>
         <authors>
            <author id="CMS">
               <born>
                  1922-11-26
               </born>
               <dead>
                  2000-02-12
               </dead>
               <name>
                  <complex-name>
                     <last-name>
                        Schulz
                     </last-name>
                     <first-name>
                        Charles
                     </first-name>
                     <middle-name>
                        M.
                     </middle-name>
                  </complex-name>
               </name>
            </author>
         </authors>
         <characters>
            <character id="PP">
               <name>
                  <complex-name>
                     <first-name>
                        Peppermint
                     </first-name>
                     <last-name>
                        Patty
                     </last-name>
                  </complex-name>
               </name>
               <qualification>
                  kühn, dreist und draufgängerisch
               </qualification>
               <born>
                  1966-08-22
               </born>
            </character>
            <character id="Snoopy">
               <born>
                  1950-10-04
               </born>
               <name>
                  <simple-name>
                     Snoopy
                  </simple-name>
               </name>
               <qualification>
                  extrovertierter Beagle
               </qualification>
            </character>
            <character id="Schroeder">
               <qualification>
                  brachte die klassische Musik in die Peanuts-Comics ein
               </qualification>
               <name>
                  <simple-name>
                     Schroeder
                  </simple-name>
               </name>
               <born>
                  1951-05-30
               </born>
            </character>
            <character id="Lucy">
               <name>
                  <simple-name>
                     Lucy
                  </simple-name>
               </name>
               <born>
                  1952-03-03
               </born>
               <qualification>
                  herrschsüchtig, kratzbürstig und egoistisch
               </qualification>
            </character>
         </characters>
      </book>
   </library>
   
               
                  
                   
                  
                   

Die Anpassung des Schemas ergibt sich dann fast von selbst und könnte so aussehen (wenn wir ein flaches Design beibehalten):

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:element name="simple-name" type="xs:token"/>
   <xs:element name="first-name" type="xs:token"/>
   <xs:element name="middle-name" type="xs:token"/>
   <xs:element name="last-name" type="xs:token"/>
   <xs:element name="qualification" type="xs:token"/>
   <xs:element name="born" type="xs:date"/>
   <xs:element name="dead" type="xs:date"/>
   <xs:element name="isbn" type="xs:NMTOKEN"/>
   <xs:attribute name="id" type="xs:ID"/>
   <xs:attribute name="available" type="xs:boolean"/>
   <xs:attribute name="lang" type="xs:language"/>
   <xs:element name="name">
      <xs:complexType>
         <xs:choice>
            <xs:element ref="simple-name"/>
            <xs:element ref="complex-name"/>
         </xs:choice>
      </xs:complexType>
   </xs:element>
   <xs:element name="complex-name">
      <xs:complexType>
         <xs:all>
            <xs:element ref="first-name"/>
            <xs:element ref="middle-name" minOccurs="0"/>
            <xs:element ref="last-name"/>
         </xs:all>
      </xs:complexType>
   </xs:element>
   <xs:element name="title">
      <xs:complexType>
         <xs:simpleContent>
            <xs:extension base="xs:token">
               <xs:attribute ref="lang"/>
            </xs:extension>
         </xs:simpleContent>
      </xs:complexType>
   </xs:element>
   <xs:element name="library">
      <xs:complexType>
         <xs:sequence>
            <xs:element ref="book" maxOccurs="unbounded"/>
         </xs:sequence>
      </xs:complexType>
   </xs:element>
   <xs:element name="authors">
      <xs:complexType>
         <xs:sequence>
            <xs:element ref="author" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
      </xs:complexType>
   </xs:element>
   <xs:element name="author">
      <xs:complexType>
         <xs:all>
            <xs:element ref="name"/>
            <xs:element ref="born"/>
            <xs:element ref="dead" minOccurs="0"/>
         </xs:all>
         <xs:attribute ref="id"/>
      </xs:complexType>
   </xs:element>
   <xs:element name="book">
      <xs:complexType>
         <xs:all>
            <xs:element ref="isbn"/>
            <xs:element ref="title"/>
            <xs:element ref="authors"/>
            <xs:element ref="characters"/>
         </xs:all>
         <xs:attribute ref="id"/>
         <xs:attribute ref="available"/>
      </xs:complexType>
   </xs:element>
   <xs:element name="characters">
      <xs:complexType>
         <xs:sequence>
            <xs:element ref="character" minOccurs="0"
               maxOccurs="unbounded"/>
         </xs:sequence>
      </xs:complexType>
   </xs:element>
   <xs:element name="character">
      <xs:complexType>
         <xs:all>
            <xs:element ref="name"/>
            <xs:element ref="born"/>
            <xs:element ref="qualification"/>
         </xs:all>
         <xs:attribute ref="id"/>
      </xs:complexType>
   </xs:element>
</xs:schema

Dieser Vorgang kann verallgemeinert und auch für andere Zwecke als die Anpassung von Instanzdokumenten an die Beschränkungen von xs:all verwendet werden. Interessant ist hier die Beobachtung, daß wir die Komplexität »externalisiert« haben. Vorher lag sie vor dem Instanzdokument verborgen im Schema, nun wird die volle Struktur des Inhaltsmodells in das Instanzdokument selbst eingebracht. Die Auswahlen und Sequenzen (ein Element mit mehrfachem Auftreten ist nichts anderes als eine implizite Sequenz) werden nun durch Container in den Instanzdokumenten ausgedrückt. Da die Struktur dort nun deutlicher zutage tritt, kann das Ergebnis als besser lesbar angesehen werden. Einige Autoren betrachten es als gute Praxis, solche Container zu benutzen.

xs:choise statt xs:all verwenden

Wenn es nicht möglich oder nicht praktikabel ist, die Dokumentstruktur den Beschränkungen von xs:all anzupassen, besteht ein weiterer Ausweg darin, xs:all-Kompositoren durch xs:choice zu ersetzen, wann immer dies möglich ist. Dieser Trick ist wesentlich weniger allgemein als die eben besprochene Strukturanpassung, und es mag überraschend erscheinen, daß zwei Kompositoren mit so unterschiedlicher Bedeutung »austauschbar« sein könnten. Dies trifft nur zu, wenn man eine lockere Kontrolle über die Anzahl der Nennungen hat, etwa innerhalb eines Containers, der sowohl author- als auch character-Elemente in beliebiger Reihenfolge mit beliebig häufigem Vorkommen akzeptiert. Ein solcher Container kann so definiert werden:

<xs:element name="persons">
   <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
         <xs:element ref="author"/>
         <xs:element ref="character"/>
      </xs:choice>
   </xs:complexType>
</xs:element>

Diese Definition hat dieselbe Bedeutung wie die folgende verbotene Definition mit xs:all:

<xs:element name="persons">
   <xs:complexType>
      <xs:all>
         <xs:element ref="author" minOccurs="0" maxOccurs="unbounded"/>
         <xs:element ref="character" minOccurs="0"
            maxOccurs="unbounded"/>
      </xs:all>
   </xs:complexType>
</xs:element>

Ableitung komplexer Inhalte

Komplexe Inhalte können auch durch Erweiterung oder durch Einschränkung von komplexen Typen abgeleitet werden. Bevor wir uns die Einzelheiten dieser Mechanismen ansehen, sollten wir bemerken, daß sie nicht symmetrisch sind und daß sie sich in ihrer Semantik stark voneinander unterscheiden. Die Ableitung komplexer Inhalte durch Einschränkung ist eine Einschränkung für die Menge der passenden Instanzen. Alle Instanzstrukturen, die zu dem eingeschränkten komplexen Typ passen, müssen auch auf den Basistyp passen. Die Ableitung komplexer Inhalte durch Erweiterung eines komplexen Typs ist eine Erweiterung des Inhaltsmodells durch Hinzufügung neuer Partikeln. Ein Inhalt, der auf den Basistyp paßt, paßt nicht unbedingt auch auf den erweiterten komplexen Typ. Das bedeutet auch, daß es keine »Rundfahrt« gibt: Im allgemeinen kann weder ein eingeschränkter noch ein erweiterter Typ so erweitert bzw. eingeschränkt werden, daß wieder der Basistyp entsteht.

Ableitung durch Erweiterung

Ableitung durch Erweiterung ähnelt der Erweiterung komplexer Typen mit einfachem Inhalt. Funktional ist sie dem Vorgang, Element- oder Attributgruppen zwecks Erzeugung eines neuen komplexen Typs zu verbinden, sehr ähnlich. Das Ziel ist dabei, den bereits im Basistyp definierten Elementen und Attributen neue hinzufügen zu können. Das ist mehr oder weniger dasselbe wie die Erzeugung einer Sequenz, in der das neue Inhaltsmodell auf das alte Inhaltsmodell folgt. Kehren wir zu unserer Bibliothek zurück, um dies zu veranschaulichen. Die Inhaltsmodelle unserer Elemente author und character sind einander recht ähnlich: author erwartet name, born und dead, während character name, born und qualification erwartet. Wenn wir eine Ableitung durch Erweiterung verwenden wollen, können wir zunächst einen Basistyp anlegen, der die ersten Elemente enthält, die den Inhaltsmodellen beider Elemente gemeinsam ist:

<xs:complexType name="basePerson">
   <xs:sequence>
      <xs:element ref="name"/>
      <xs:element ref="born"/>
   </xs:sequence>
   <xs:attribute ref="id"/>
</xs:complexType>

Nun ist es möglich, Ableitungen durch Erweiterung zu verwenden, um neue Elemente (dead für author und qualification für character) an die, die bereits im Basistyp definiert worden sind, anzuhängen:

<xs:element name="author">
   <xs:complexType>
      <xs:complexContent>
         <xs:extension base="basePerson">
            <xs:sequence>
               <xs:element ref="dead" minOccurs="0"/>
            </xs:sequence>
         </xs:extension>
      </xs:complexContent>
   </xs:complexType>
</xs:element>


<xs:element name="character">
   <xs:complexType>
      <xs:complexContent>
         <xs:extension base="basePerson">
            <xs:sequence>
               <xs:element ref="qualification"/>
            </xs:sequence>
         </xs:extension>
      </xs:complexContent>
   </xs:complexType>
</xs:element>

Technisch gesprochen, ist die Bedeutung dieser Ableitung äquivalent zur Erzeugung einer Sequenz, die zunächst den Kompositor, der den Basistyp definiert, enthält, und dahinter den Kompositor, der in dem Element xs:extension genannt ist. Daher sind die Inhaltsmodelle dieser Elemente den folgenden Inhaltsmodellen sehr ähnlich:

<xs:element name="author">
   <xs:complexType>
      <xs:sequence>
         <xs:sequence>
            <xs:element ref="name"/>
            <xs:element ref="born"/>
         </xs:sequence>
         <xs:sequence>
            <xs:element ref="dead" minOccurs="0"/>
         </xs:sequence>
      </xs:sequence>
      <xs:attribute ref="id"/>
   </xs:complexType>
</xs:element>


<xs:element name="character">
   <xs:complexType>
      <xs:sequence>
         <xs:sequence>
            <xs:element ref="name"/>
            <xs:element ref="born"/>
         </xs:sequence>
         <xs:sequence>
            <xs:element ref="qualification"/>
         </xs:sequence>
      </xs:sequence>
      <xs:attribute ref="id"/>
   </xs:complexType>
</xs:element>

Diese Äquivalenz zeigt klar den Charakter dieses Ableitungsmechanismus. Wie in der Einführung zu den Ableitungsmechanismen für komplexe Inhalte festgestellt, handelt es sich hier nicht um eine Erweiterung der Menge zulässiger Instanzstrukturen. Ein Element character, das ein notwendiges Kindelement qualification hat, kann kein gültiges basePerson-Inhaltsmodell haben, sondern nur die Verschmelzung zweier Inhaltsmodelle. Diese Verschmelzung ist ihren eigenen Begrenzungen unterworfen: Sie können den Punkt, an dem das neue Inhaltsmodell eingefügt wird, nicht selbst wählen. Der neue Kompositor wird stets hinter dem des Basistyps eingefügt. Wenn in unserem Beispiel die gemeinsamen Elemente name und born nicht die ersten beiden Elemente wären, hätten wir keine Ableitung durch Erweiterung verwenden können.

Zudem müssen wir beachten, daß wir bei Ableitungen durch Erweiterung den Kompositor, der zum Verschmelzen der beiden Inhaltsmodelle verwendet wird, nicht selbst wählen können. Wenn wir Inhaltsmodelle ableiten, die xs:choice als Kompositoren verwenden, bedeutet das also, daß nicht etwa der Bereich der Auswahlmöglichkeiten erweitert wird, sondern daß die Auswahlen in einer xs:sequence aufeinanderfolgen. Wir könnten beispielsweise das Inhaltsmodell des Elements persons erweitern, das wir eben erzeugt haben und das als globaler komplexer Typ definiert werden könnte:

<xs:complexType name="basePersons">
   <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element ref="author"/>
      <xs:element ref="character"/>
   </xs:choice>
</xs:complexType>

Angenommen, wir fügen ein neues Element mit Hilfe einer Ableitung durch Erweiterung hinzu:

<xs:complexType name="persons">
   <xs:complexContent>
      <xs:extension base="basePersons">
         <xs:sequence>
            <xs:element name="editor" type="xs:token" minOccurs="0"
               maxOccurs="unbounded"/>
         </xs:sequence>
      </xs:extension>
   </xs:complexContent>
</xs:complexType>

Dann ist das Ergebnis ein Inhaltstyp, der zu dem folgenden äquivalent ist:

<xs:complexType name="personsEquivalent">
   <xs:sequence>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
         <xs:element ref="author"/>
         <xs:element ref="character"/>
      </xs:choice>
      <xs:sequence>
         <xs:element name="editor" type="xs:token" minOccurs="0"
            maxOccurs="unbounded"/>
      </xs:sequence>
   </xs:sequence>
</xs:complexType>

Es ist unmöglich, eine Erweiterung der xs:choice wie die folgende zu realisieren:

<xs:complexType name="personsAsWeWouldHaveLiked">
   <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element ref="author"/>
      <xs:element ref="character"/>
      <xs:element name="editor" type="xs:token"/>
   </xs:choice>
</xs:complexType>

Die Situation ist für xs:all sogar noch schlimmer: Die Einschränkungen für die Zusammensetzung von xs:all gelten weiterhin. Das bedeutet, daß Sie einem komplexen Typ, der mit einem xs:all definiert ist, keinerlei neuen Inhalt hinzufügen können – Sie können allerdings noch neue Attribute hinzufügen – und daß Sie einen xs:all-Kompositor in einer Ableitung durch Erweiterung nur verwenden können, wenn der Basistyp ein leeres Inhaltsmodell hat.

Ableitung durch Einschränkung

Während Ableitung durch Erweiterung dem Verschmelzen zweier Inhaltsmodelle durch den Kompositor xs:sequence (außerhalb einer Gruppe) ähnelt, ist die Ableitung durch Einschränkung eine Einschränkung der Anzahl von Instanzstrukturen, die zu dem komplexen Typ paßt. In dieser Hinsicht ist sie der Ableitung durch Einschränkung bei einfachen Datentypen oder bei komplexen Typen einfachen Inhalts ähnlich (auch wenn, wie wir gesehen haben, eine Facette wie xs:whitespace die Anzahl der Instanzdokumente, die zu einem einfachen Typ passen, erweitert). Dies ist allerdings die einzige Ähnlichkeit der Ableitungen durch Einschränkung bei einfachen bzw. komplexen Datentypen. Das ist in hohem Maße verwirrend, denn W3C XML Schema benutzt in beiden Fällen dasselbe Wort und sogar denselben Elementnamen. Dennoch haben diese Wörter unterschiedliche Bedeutungen, und die Inhaltsmodelle der xs:restriction-Elemente sind unterschiedlich.

Anders als bei der Ableitung einfacher Typen gibt es keine Facetten, die auf komplexe Typen angewendet werden können. Die Ableitung geschieht, indem das vollständige Inhaltsmodell des abgeleiteten Datentyps definiert wird, das eine logische Einschränkung des Basistyps sein muß. Jede gemäß dem abgeleiteten Datentyp zulässige Instanzstruktur muß auch nach dem Basis-Datentyp zulässig sein. Die Spezifikation von W3C XML Schema definiert die Ableitung durch Einschränkung nicht in diesen Worten, sondern legt einen nahezu äquivalenten Algorithmus fest, dem Schema-Prozessoren folgen müssen.

Die Ableitung eines komplexen Typs durch Einschränkung bekundet die Absicht, daß der abgeleitete Typ eine Teilmenge des Basistyps sein soll. (Anders als bei der Ableitung für einfache Typen wird diese Bekundung benötigt, wenn man Ersetzungen und Neudefinitionen von Typen verwenden will, wie wir unter Konstruktion von Bausteinen und unter Objektorientierte Konstruktion weiterer Bausteine sehen werden. Dort kann sie nützliche Informationen zur Verfügung stellen, die von einigen Applikationen verwendet werden können.) Wenn wir einfache Typen ableiten, können wir einen Basistyp nehmen, ohne uns um die Einzelheiten zu kümmern, welche Facetten bereits angewendet worden sind, und einfach unseren eigenen Satz an Facetten hinzufügen. Im Gegensatz dazu müssen wir hier eine vollständige Definition eines Inhaltsmodells angeben. Eine Ausnahme bilden Attribute, die mit »prohibited« als verboten deklariert werden können, um sie aus der Einschränkung auszuschließen, wie bereits bei der Einschränkung komplexer Typen mit einfachem Inhalt kennengelernt.

Fahren wir fort und versuchen wir, eine Basis zu finden, von der wir die beiden Elemente author und character durch Einschränkung ableiten können. Diesmal können wir sicher sein, daß es einen solchen komplexen Typ gibt, denn alle komplexen Typen können von einem abstrakten xs:anyType abgeleitet werden, der beliebige Elemente und Attribute zuläßt. Im echten Leben werden wir jedoch versuchen, den restriktivsten Basistyp zu finden, der unsere Bedürfnisse erfüllen kann. Da die Elemente name und born sowohl in author als auch in character auftreten, und zwar mit der gleichen Auftretenshäufigkeit, können wir sie so beibehalten, wie sie erscheinen. Wir haben dann zwei Elemente (dead und qualification), die nur in jeweils einem der beiden Elemente author und character zu finden sind. Da sowohl author als auch character gemäß dem Basistyp gültig sein müssen, werden wir beide Kindelemente in den Basistyp aufnehmen. Wir werden sie jedoch optional machen, indem wir dem Attribut minOccurs den Wert 0 geben. Der Basistyp kann dann so aussehen:

<xs:complexType name="person">
   <xs:sequence>
      <xs:element ref="name"/>
      <xs:element ref="born"/>
      <xs:element ref="dead" minOccurs="0"/>
      <xs:element ref="qualification" minOccurs="0"/>
   </xs:sequence>
   <xs:attribute ref="id"/>
</xs:complexType>

Die Ableitungen geschehen nun durch Definition der Inhaltsmodelle innerhalb eines xs:restriction-Elements. (Beachten Sie, daß wir die Attribut-Deklarationen nicht wiederholen, die unverändert bleiben.)

<xs:element name="author">
   <xs:complexType>
      <xs:complexContent>
         <xs:restriction base="person">
            <xs:sequence>
               <xs:element ref="name"/>
               <xs:element ref="born"/>
               <xs:element ref="dead" minOccurs="0"/>
            </xs:sequence>
         </xs:restriction>
      </xs:complexContent>
   </xs:complexType>
</xs:element>

<xs:element name="character">
   <xs:complexType>
      <xs:complexContent>
         <xs:restriction base="person">
            <xs:sequence>
               <xs:element ref="name"/>
               <xs:element ref="born"/>
               <xs:element ref="qualification"/>
            </xs:sequence>
         </xs:restriction>
      </xs:complexContent>
   </xs:complexType>
</xs:element>

Die Schreibweise für eine Ableitung durch Einschränkung ist also länger als die für eine unmittelbare Definition des Inhaltsmodells. Der Zweck dieser Ableitung besteht nicht darin, modulare Schemas zu bauen, sondern darin, Anwendungen, die dieses Schema benutzen, den Hinweis zu geben, daß es einige Gemeinsamkeiten der Inhaltsmodelle gibt. Wenn diese Anwendungen wissen, wie man mit dem komplexen Typ person umgeht, können sie auch mit den Elementen author und character arbeiten.

Eine Änderung der Auftretenshäufigkeit von Partikeln ist nicht die einzige Änderung, die mit einer Ableitung durch Einschränkung erreicht werden kann. Andere Vorgänge, die zu einer Verringerung der Anzahl gültiger Instanzstrukturen führen, sind ebenfalls möglich, so etwa der Übergang von einem einfachen Typ zu einem stärker eingeschränkten oder die Fixierung eines Werts. Die Haupteinschränkung bei diesem Mechanismus besteht darin, daß jede Partikel des abgeleiteten Typs eine ausdrückliche Ableitung der entsprechenden Partikel des Basistyps sein muß. Aus dieser Aussage folgt eine Beschränkung der »Tiefe« der Einschränkungen, die in einem einzigen Schritt erreicht werden kann. Wenn wir Partikeln auf einer tieferen Schachtelungsebene einschränken wollen, müssen wir möglicherweise lokale Definitionen in globale umwandeln. Wir werden ein konkretes Beispiel im Abschnitt »Erzeugung gemischter Inhaltsmodelle« geben, die in dieser Hinsicht ähnlich sind.

Asymmetrie dieser beiden Methoden

Wir haben nun alle benötigten Elemente, um auf unsere Behauptung zurückzukommen, daß diese beiden Ableitungsmethoden nicht symmetrisch sind. Dieser Mangel an Symmetrie ist an sich kein Fehler, aber wenn man ihn genauer untersucht, versteht man die Bedeutung dieser beiden Ableitungsmethoden besser. Nehmen wir uns die Ableitung des Elements character durch Erweiterung von basePerson vor:

<xs:complexType name="basePerson">
   <xs:sequence>
      <xs:element ref="name"/>
      <xs:element ref="born"/>
   </xs:sequence>
   <xs:attribute ref="id"/>
</xs:complexType>


<xs:element name="character">
   <xs:complexType>
      <xs:complexContent>
         <xs:extension base="basePerson">
            <xs:sequence>
               <xs:element ref="qualification"/>
            </xs:sequence>
         </xs:extension>
      </xs:complexContent>
   </xs:complexType>
</xs:element>

Das Inhaltsmodell von character enthält ein notwendiges Element qualification . Gültige Instanzen von character sind nicht gültig gemäß basePerson und umgekehrt; daher besteht keine Hoffnung, aus character durch Einschränkung wieder einen Typ basePerson zu machen, denn alle Instanzstrukturen, die gemäß dem abgeleiteten Typ gültig sind, müssen bei einer Ableitung durch Einschränkung auch gemäß dem Basistyp gültig sein.

Sehen wir uns nun noch einmal die Ableitung des Elements character durch Einschränkung des Basistyps person an:

<xs:complexType name="person">
   <xs:sequence>
      <xs:element ref="name"/>
      <xs:element ref="born"/>
      <xs:element ref="dead" minOccurs="0"/>
      <xs:element ref="qualification" minOccurs="0"/>
   </xs:sequence>
   <xs:attribute ref="id"/>
</xs:complexType>


<xs:element name="character">
   <xs:complexType>
      <xs:complexContent>
         <xs:restriction base="person">
            <xs:sequence>
               <xs:element ref="name"/>
               <xs:element ref="born"/>
               <xs:element ref="qualification"/>
            </xs:sequence>
         </xs:restriction>
      </xs:complexContent>
   </xs:complexType>
</xs:element>

Auch hier ist es nicht möglich, aus dem komplexen Typ character wieder den Typ person zu machen, denn dies würde bedeuten, daß die minimale Auftretenshäufigkeit für qualification von 1 auf 0 geändert und ein optionales Element dead zwischen born und qualification eingefügt werden müßte. Beides ist im Zuge einer Ableitung durch Erweiterung nicht möglich, bei der neue Inhalte nur an die Inhalte des Basistyps angehängt werden können. Weder kann eine bestehende Partikel (zur Änderung der Häufigkeit des Auftretens) modifiziert noch kann eine neue Partikel zwischen zwei bereits vorliegende Partikeln eingefügt werden.

   

zum Seitenanfang

<< zurück vor >>

 

 

 

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

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

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