## 16.2 Gültigkeit eines XML-Dokuments Der XML-Standard definiert selbst keine Elemente (Tags), sondern beschreibt nur die Wohlgeformtheit. Für den Datenaustausch zwischen Anwendungen oder Systemen ist das meist nicht ausreichend, denn dazu bedarf es zusätzlich eines festen Musters, wie die Elemente im XML-Dokument strukturiert werden. Wird ein XML-Dokument zwischen zwei Anwendungen ausgetauscht, müssen sich beide Anwendungen in dieser Hinsicht an dieselben Vorgaben halten, um die korrekte Interpretation der Daten zu gewährleisten. In der Datenverarbeitung ist ein Schema ein allgemeingültiger Begriff für eine Beschreibung einer Menge von Daten. Im Kontext von XML ist ein Schema die Beschreibung eines XML-Dokuments. Mithilfe eines Schemas wird die Gültigkeit von XML-Dokumenten überprüft. Ein XML-Dokument, das die im Schema definierten Regeln einhält, gilt als wohlgeformt und gültig. Ein solches Dokument kann von jeder Anwendung in Verbindung mit dem Schema richtig verarbeitet werden. Ein Schema wird speziell für ein ganz bestimmtes XML-Dokument bereitgestellt und kann auf zweierlei Art mit einem Dokument verknüpft werden: Das Schema ist selbst Bestandteil des XML-Dokuments. Das Schema wird als separate Datei bereitgestellt.
Hinweis
Es gibt drei wesentliche Schemata zur Beschreibung der Gültigkeit: Document Type Definition (DTD), XML Schema (XSD) und XML Data Reduced (XDR). In den vergangenen Jahren hat sich XSD zu einem Quasi-Standard entwickelt. Das liegt sicher nicht nur daran, dass XSD mehr Möglichkeiten bietet als DTD, sondern darüber hinaus kann ein XSD-Schema mittels passender Tools schneller bereitgestellt werden als eine auf DTD basierende Dokumenttyp-Definition. XDR ist eine Schemadefinition aus dem Hause Microsoft, die aber von Microsoft selbst nicht mehr unterstützt wird. Aus den genannten Gründen werden wir uns an dieser Stelle ausschließlich mit XSD beschäftigen.
### 16.2.1 XML Schema (XSD) XSD (XML Schema) ist seit 2001 eine Empfehlung des W3-Konsortiums, um den Inhalt und die Struktur eines XML-Dokuments zu beschreiben. XML Schemas basieren ihrerseits selbst auf XML. Nach dem aktuellen Stand stehen Ihnen insgesamt 44 vordefinierte Datentypen zur Verfügung, z. B. int, short, float oder date. Zudem lassen sich aber auch darüber hinaus benutzerdefinierte Typen beschreiben sowie die Reihenfolge, in der die Elemente auftreten. Betrachten wir exemplarisch die folgende XML-Datei Personen.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <Personen>
      <Person>
        <Name>Walter Meier</Name>
        <Wohnort>Frankfurt</Wohnort>
      </Person>
    </Personen>
Die Schema-Datei Personen.xsd, die die Struktur dieses XML-Dokuments beschreibt, sieht wie folgt aus:
    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema id="Personen" xmlns=""
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
      <xs:element name="Personen" msdata:IsDataSet="true" msdata:Locale="en-US">
        <xs:complexType>
          <xs:choice minOccurs="0" maxOccurs="unbounded">
            <xs:element name="Person">
              <xs:complexType>
                <xs:sequence>
                  <xs:element name="Name" type="xs:string" minOccurs="0" />
                  <xs:element name="Wohnort" type="xs:string" minOccurs="0" />
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:choice>
        </xs:complexType>
      </xs:element>
    </xs:schema>
#### Das Tool »xsd.exe« Ein neues XML-Dokument zu erstellen, stellt keine große Hürde dar, wenn die Wohlgeformtheitsregeln beachtet werden. Ganz anders sieht es aus, wenn Sie ein XML Schema bereitstellen wollen, mit dessen Hilfe Sie ein bestimmtes XML-Dokument validieren wollen. Dazu sind viele spezifische Kenntnisse erforderlich, um am Ende das erforderliche Ergebnis zu erreichen. Erfreulicherweise wird uns aber die Arbeit von dem Kommandozeilentool xsd.exe abgenommen, das zusammen mit Visual Studio 2010 geliefert wird und standardmäßig im Ordner \Programme\Microsoft SDKs\Windows\v7.0A\bin zu finden ist. Das Tool kann vielfältig benutzt werden. Wenn Sie eine XML-Datei angeben (Erweiterung .XML), leitet xsd.exe ein Schema aus den Daten in der Datei ab und erstellt ein XSD-Schema. Die Ausgabedatei erhält den Namen der XML-Datei mit der Erweiterung .xsd, z. B.:
    xsd.exe Personen.xml
Mit dieser Anweisung wird zu der XML-Datei Personen.xml ein passendes XML Schemanamens Personen.xsd erzeugt. Obwohl Ihnen xsd.exe eigentlich die meiste Arbeit abnimmt, sollten Sie dennoch die wesentlichsten Elemente eines XML Schemas verstehen, denn Anpassungen lassen sich nicht generell ausschließen. Im folgenden Abschnitt sehen wir uns den Inhalt eines XML Schemas an. ### 16.2.2 XML-Dokument mit einem XML Schema verknüpfen Um ein XML-Dokument mit einem externen XML Schema zu verbinden, müssen Sie im Stammelement des XML-Dokuments den Namespace
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
angeben. Üblicherweise wird dabei das Präfix xsi verwendet. Anschließend wird die mit dem XML-Dokument zu verknüpfende Schema-Datei festgelegt. Dazu bieten sich mit den Attributen noNamespaceSchemaLocation und schemaLocation zwei Möglichkeiten. Ausgangspunkt der nachfolgenden Betrachtungen sei erneut das XML-Dokument Personen.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <Personen>
      <Person>
        <Name>Walter Meier</Name>
        <Wohnort>Frankfurt</Wohnort>
      </Person>
    </Personen>
Die XML-Schema-Datei entspricht damit exakt der, die bereits weiter oben gezeigt wurde. #### Das Attribut »noNamespaceSchemaLocation« Das Attribut noNamespaceSchemaLocation verwenden Sie, wenn den im XSD-Dokument beschriebenen Elementen kein spezifischer Namespace zugeordnet werden soll. Das ist in unserem Beispieldokument der Fall. Wir können das XML-Dokument mit einer Schema-Datei verknüpfen, indem wir das Attribut noNamespaceSchemaLocation verwenden und die Schema-Datei angeben.
    <Personen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:noNamespaceSchemaLocation="Personen.xsd">
Als Wert verwenden Sie die absolute oder relative Pfadangabe der Schema-Datei. Die Validierung lässt sich recht gut mit XML-Notepad 2007 prüfen. Öffnen Sie dieses Tool, und laden Sie die XML-Datei in den Editor. Es wird kein Fehler angezeigt. Sie können nun die Auswirkung eines Validierungsfehlers testen. Dazu müssen Sie zuerst eine Änderung in der XSD-Datei vornehmen. Öffnen Sie die Schema-Datei, und ändern Sie das Attribut minOccurs des Elements Name vom Wert 0 in 1 ab. Damit legen Sie fest, dass das Element Name in jedem Fall angegeben werden muss. Speichern Sie die Schema-Datei, und öffnen Sie Personen.xml.
    <xs:element name="Name" type="xs:string" minOccurs="0" />
Im nächsten Schritt löschen Sie das <Name>-Element in der XML-Datei, speichern diese und öffnen sie erneut in XML-Notepad. Da das XML-Dokument nicht mehr den Vorgaben in der Schema-Datei entspricht, wird sofort ein Validierungsfehler angezeigt (siehe Abbildung 16.4).
Hinweis
Anstatt des hier beschriebenen Attributs noNamespaceSchemaLocation können Sie auch, wie im folgenden Abschnitt gezeigt, das Attribut schemaLocation verwenden.
Hier klicken, um das Bild zu vergrößern Abbildung 16.4 Validierungsfehler in XML-Notepad 2007 #### Das Attribut »schemaLocation« Das Attribut schemaLocation findet Verwendung, wenn die in einer Schema-Datei beschriebenen Elemente im XML-Dokument mit einem spezifischen Namespace in Beziehung gesetzt werden sollen. Angenommen, wir würden für das Element <Person> einen Namespace wie folgt festlegen:
    <?xml version="1.0" encoding="utf-8"?>
    <Personen xmlns:pers="http://www.tollsoft.de"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.tollsoft.de Personen.xsd">
      <pers:Person>
        <Name>Walter</Name>
        <Wohnort>Frankfurt</Wohnort>
      </pers:Person>
    </Personen>
Es wird im XML-Dokument auf die Schema-Datei Personen.xsd verwiesen. Alle dort beschriebenen Elemente werden dem Namespace http://www.tollsoft.de zugeordnet, für den im XML-Dokument das Präfix pers gesetzt ist. In der Praxis werden manchmal mehrere einzelne XML-Dokumente zusammengeführt, um daraus ein Dokument zu formen, in dem alle Daten der Einzeldokumente enthalten sind. Auch hierzu eignet sich das Attribut schemaLocation. Die einzelnen XML Schemas werden unter Angabe des jeweils zugeordneten spezifischen Namespace der Reihe nach im Attribut aufgelistet. Auch dazu ein Beispiel:
    <?xml version="1.0"?>
    <p:Person
       xmlns:p="http://NS1"
       xmlns:a="http://NS2"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://NS1 Person.xsd
                                      http://NS2 Auto.xsd">
      <Name>John</Name>
      <Alter>45</Alter>
      <a:Auto>
        <Farbe>rot</Farbe>
        <Sitze>4</Sitze>
      </a:Auto>
    </p:Person>
Das gezeigte XML-Dokument führt die in zwei separaten XML-Dokumenten enthaltenen Daten zusammen. Das erste Dokument beschreibt das <Person>-Element, das zweite das <Auto>-Element. Das Gesamtdokument soll dem Zweck dienen, einer Person ein bestimmtes Auto zuzuordnen. Die Schema-Informationen stammen aus den Schema-Dateien Person.xsd und Auto.xsd. Im Attribut schemaLocation wird Person.xsd mit dem Namespace NS1 in Beziehung gesetzt, Auto.xsd mit dem Namespace NS2. Darüber hinaus werden mit
    xmlns:p="http://NS1"
    xmlns:a="http://NS2"
beide Namespaces durch Präfixe beschrieben. Die beiden Elemente <Person> und <Auto> im XML-Dokument können nun aufgrund der Präfixangabe eindeutig einem XML Schema zugeordnet werden. Weiter unten in diesem Kapitel wird das Attribut targetNamespace eines XML Schemas erläutert. In diesem Zusammenhang werden Sie auch noch weitere Informationen hinsichtlich der hier vorgestellten Attribute noNamespaceSchemaLocation und schemaLocation erhalten. ### 16.2.3 Struktur eines XML Schemas #### Grundstruktur Das folgende Beispiel zeigt Ihnen einige grundlegende Elemente in einer einfachen Struktur. Darin sind Elemente enthalten, die in fast jedem XML Schema auftreten können.
    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" ... >
      <xs:element name="Stammelement">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="Unterelement1"/>
            <xs:element name="Unterelement2"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
Das Element schema bildet das Wurzelelement eines XML Schemas. Es beschreibt eine Reihe von Namespaces. Der wichtigste ist in dem Beispiel angegeben, nämlich http://www.w3.org/2001/XMLSchema, der üblicherweise durch das Präfix xs beschrieben wird. Diesem Namespace sind alle vordefinierten Elemente des XML Schemas zugeordnet. #### Einfache Elemente Ein Element, das selbst keine Attribute und untergeordneten Elemente enthalten kann, wird als einfaches Element bezeichnet. Es beschreibt ein Tag in einem XML-Dokument. Einfache Elemente werden über xs:element definiert. Der Bezeichner wird über das Attribut name festgelegt, der Datentyp über type.
    <xs:element name="Elementname" type="xs:Datentyp" />
Mit dem zusätzlichen Attribut default können Sie einen Standardwert bestimmen, mit fixed einen festen Wert. #### Attribute Ein einfaches Element, wie es im Abschnitt zuvor beschrieben worden ist, kann keine Attribute haben. Ein Element mit Attributen im XML-Dokument muss als komplexes Element definiert sein (siehe dazu auch den folgenden Abschnitt). Innerhalb eines komplexen Elements wird ein Attribut ähnlich einem einfachen Element beschrieben.
    <xs:attribute name ="Attributname" type="xs:Datentyp" />
Darüber hinaus lassen sich auch die zusätzlichen Attribute default und fixed angeben, die dieselbe Bedeutung haben wie bei den einfachen Elementen. Interessant ist noch ein weiteres mögliches Attribut: use. Mit diesem können Sie festlegen, ob das Attribut im XML-Dokument angegeben werden muss. Die möglichen Werte für use sind required (zwingend erforderlich), optional (wahlweise) und prohibited (verboten). Wird use nicht angegeben, gilt ein Attribut als optional. Beispiel:
    <xs:attribute name ="Attributname" type="xs:Datentyp" use="required" />
Eine besondere Bedeutung kommt der Positionsangabe der Attribute im XML Schema zu, denn die Definition von Attributen darf nur am Ende eines komplexen Elements, direkt vor dem schließenden Tag </xs:element> erfolgen. Soll zum Beispiel das folgende Element in einem XML Schema beschrieben werden
    <Adresse Ort="Bonn" Strasse="Neuestr.34"></Adresse>
müsste die entsprechende Passage wie folgt lauten:
    <xs:element name="Adresse" minOccurs="0" maxOccurs="unbounded">
      <xs:complexType>
        <xs:attribute name="Ort" type="xs:string" />
        <xs:attribute name="Strasse" type="xs:string" />
      </xs:complexType>
    </xs:element>
#### Komplexe Elemente Komplexe Elemente in einem XML Schema beschreiben XML-Dokument-Elemente, die Attribute oder weitere, untergeordnete Elemente aufweisen. Betrachten Sie als Beispiel den folgenden Ausschnitt aus einer XML-Datei:
    <Person>
      <Vorname>Manfred</Vorname>
      <Telefon/>
      <Zuname>Fischer</Zuname>
    </Person>
Das Element <Person> wird beschrieben durch die untergeordneten Elemente <Vorname>, <Zuname> und <Telefon>. Dieser Ausschnitt könnte in einem XML Schema folgendermaßen definiert werden:
    <xs:element name="Person">
      <xs:complexType>
        <xs:sequence>
          <xs:element name="Vorname" type="xs:string" minOccurs="0" />
          <xs:element name="Telefon" type="xs:string" minOccurs="0" />
          <xs:element name="Zuname" type="xs:string" minOccurs="0" />
        </xs:sequence>
      </xs:complexType>
    </xs:element>
Wie zu erkennen ist, wird das Element <Person> mit <complexType> als komplexes Element angelegt. Das Element <sequence> legt fest, dass die nachfolgenden Elemente in der angegebenen Reihenfolge im XML-Dokument erscheinen müssen, also zuerst <Vorname>, dann <Telefon> und zum Schluss <Zuname>. Dürfen die Unterelemente in einer beliebigen Reihenfolge im XML-Dokument auftreten, dann wird die Liste dieser Elemente anstatt mit <sequence> mit <all> beschrieben.
    <xs:element name="Person">
      <xs:complexType>
        <xs:all>
          <xs:element name="Vorname" type="xs:string" minOccurs="0" />
          <xs:element name="Telefon" type="xs:string" minOccurs="0" />
          <xs:element name="Zuname" type="xs:string" minOccurs="0" />
        </xs:all>
      </xs:complexType>
    </xs:element>
Es gibt mit <choice> noch eine dritte Variante, komplexe Elemente zu beschreiben. Damit lässt sich eine Auswahl von Elementen festlegen. In einem XML-Dokument darf allerdings nur eines der angegebenen Elemente auftreten. Im folgenden Codefragment muss entweder Mann oder Frau als Element von Person erscheinen.
    <xs:element name="Person">
      <xs:complexType>
        <xs:choice>
          <xs:element name="Mann" type="xs:string" />
          <xs:element name="Frau" type="xs:string" />
        </xs:choice>
      </xs:complexType>
    </xs:element>
#### »minOccurs« und »maxOccurs« Die Attribute minOccurs und maxOccurs werden nur in komplexen Typdefinitionen angezeigt. Damit wird einschränkend festgelegt, wie oft in Folge das entsprechende Element in der entsprechenden Position in einem XML-Dokument angezeigt werden kann.
     <xs:element name="Telefon" type="xs:string"
                 minOccurs="0" maxOccurs="unbounded" />
Die Werte dieser beiden Attribute sind immer positive Zahlen. maxOccurs kann auch auf unbounded gesetzt werden, sodass eine unbegrenzte Anzahl von Elementen auftreten kann. Für sequence, all und choice sind die Werte von minOccurs und maxOccurs standardmäßig immer 1. #### Die Attribute »elementFormDefault« und »attributeFormDefault« Das Attribut elementFormDefault="qualified" erzwingt, dass alle untergeordneten Elemente im XML-Dokument demselben Namespace wie das globale Element zugeordnet sind. Betrachten Sie dazu das folgende Fragment eines XML-Schemas:
    <xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        attributeFormDefault="unqualified"
        elementFormDefault="qualified"
        targetNamespace="TestURN"
        xmlns:xs="http://www.w3.org/2001/XMLSchema">
Das folgende Dokument ist gültig, denn alle Elemente sind zweifelsfrei dem Standard-Namespace zuzuordnen, der durch TestURN beschrieben wird.
    <!--Dokument valide -->
    <Personen xmlns="TestURN"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="TestURN Personen.xsd">
      <Person>
        <Zuname>Fischer</Zuname>
        <Adresse Ort="Bonn"></Adresse>
      </Person>
    </Personen>
Das folgende XML-Dokument ist allerdings ungültig, da Personen das Präfix x vorangestellt ist. Damit wird Personen durch den Namespace TestURN qualifiziert, während alle anderen Elemente keinem spezifischen Namespace angehören.
    <!--Dokument nicht valide -->
    <x:Personen xmlns:x="TestURN"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="TestURN Personen.xsd">
      <Person>
        <Zuname>Fischer</Zuname>
        <Adresse Ort="Bonn"></Adresse>
      </Person>
    </x:Personen>
In diesem Fall müssten auch die Elemente Person, Zuname und Adresse mit dem Präfix x qualifiziert werden, damit das Dokument wieder gültig ist. Die Einstellung elementFormDefault="unqualified" schreibt den lokalen Elementen im XML-Dokument vor, dass sie keine qualifizierende Namespace-Angabe haben dürfen. Sehen wir uns auch dazu ein Beispiel an.
    <xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       attributeFormDefault="unqualified"
       elementFormDefault="unqualified"
       targetNamespace="TestURN"
       xmlns:xs="http://www.w3.org/2001/XMLSchema">
Die Validierung des folgenden XML-Dokuments schlägt fehl, denn das Element Person gehört zu dem durch den Standard-Namespace beschriebenen Namespace TestURN.
    <!--Dokument nicht valide -->
    <Personen xmlns="TestURN"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="TestURN Personen.xsd">
      <Person>
        <Zuname>Fischer</Zuname>
        <Adresse Ort="Bonn"></Adresse>
      </Person>
    </Personen>
Damit das XML-Dokument gültig ist, muss das Stammelement Personen über ein Präfix dem spezifischen Namespace TestURN zugeordnet werden und das lokale Element Person darf nicht qualifiziert werden
    <!--Dokument valide -->
    <x:Personen xmlns:x="TestURN"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="TestURN Personen.xsd">
      <Person>
        <Zuname>Fischer</Zuname>
        <Adresse Ort="Bonn"></Adresse>
      </Person>
    </x:Personen>
Das attributeFormDefault-Attribut behält am besten seinen Standardwert unqualified, nicht qualifiziert, da die meisten Schema-Autoren nicht alle Attribute ausdrücklich durch Präfixe mit Namespaces qualifizieren möchten. #### Das Attribut »targetNamespace« Das Attribut targetNamespace (Zielnamensraum) legt im XML Schema fest, welchem Namespace alle beschriebenen Elemente angehören. Im folgenden Ausschnitt ist der Zielnamensraum TestURN.
    <xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       attributeFormDefault="unqualified"
       elementFormDefault="unqualified"
       targetNamespace="TestURN"
       xmlns:xs="http://www.w3.org/2001/XMLSchema">
Ist im XML Schema das Attribut targetNamespace festgelegt, müssen Sie das im XML-Dokument berücksichtigen, indem Sie dort die Verknüpfung zwischen dem XML-Dokument und dem XML Schema über das Attribut schemaLocation definieren. schemaLocation setzt sich aus zwei Einträgen zusammen: Im ersten beschreibt man den im XML Schema festgelegten Zielnamensraum, im zweiten den absoluten oder relativen Pfad zur XSD-Datei.
    <Personen xmlns="TestURN"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="TestURN Personen.xsd">
    ...
Sie müssen vorsichtig sein, wenn Sie den Elementen im XML-Dokument einen Namespace zuordnen. Im letzten XML-Fragment ist mit
    xmlns="TestURN"
der Standard-Namespace auf den im XML Schema angegebenen Zielnamensraum festgelegt. Somit können alle Elemente anhand des Schemas validiert werden. Benutzen Sie eine andere Namensraumangabe, beispielsweise
    xmlns="urn:Personen-schema"