3.4  Schemata

XML Daten können sehr komplex werden. Da ihre Eingabe oft durch keine User-Interface Massnahmen oder sonstigte Regelungen beschränkt ist, sie im Prinzip mit jedem Texteditor verändert werden können und gewöhnlich über viele Stationen verschickt / verarbeitet werden, ist es ratsam deren formale und inhaltliche Korrektheit zu überprüfen.
Dazu wird die gute maschinelle Lesbarkeit der XML Daten von Validierungsengines ausgenützt. Es gibt viele unterschiedliche Schematypen, gegen die validiert werden kann. Das sog. Schema ist dann ein Satz von Regeln, der beim Baumdurchlauf abgeglichen wird.
Angefangen hat wohl alles mit der Dokumenttypdefinition (DTD ↗↗) die sowohl für XML Daten als auch für den Vorläufer SGML angewendet werden kann.
Die mangelnde Fähigkeit zur Überprüfung von sematischen Beziehungen mittels DTD, hat wohl zu
XML Schema geführt.
XML Schema ist konsequent mittels XML modelliert und hat dieselbe gute Eigenschaft bzgl. der Maschinenlesbarkeit, wie XML an sich. Somit können bei einem Baumdurchlauf auch komplexe Regeln beim Abgleich von Datenstruktur und Valdierungsregel maschinell überprüft werden.
Vllt. hat sich aber gerade dieser Vorteil, nämlich die Maschinenlesbarkeit, im Laufe der Zeit als Nachteil herauskristallisiert. Es gibt zwar einige sehr gute visuelle Modellierungswerkzeuge, die es erlauben die Regeln als einen Baum grafisch zu modellieren, sobald aber komplexere Beziehungen modelliert werden sollen, ist man mit diesen Tools ein bisschen gefangen und man wünscht sich doch wieder die Flexibilität eines Texteditors.
Grafische Werkzeuge sind bspw.:
Eine DTD wird im Near&Far Designer als aufklappbare Baumstruktur angezeigt. So könnnen auch sehr komplexe DTDs mit 1000 Elementen effizient untersucht werden. Über einen Eingabedialog lassen sich Attribute hinzufügen oder ändern. Auch das Neuanlegen von einzelnen Zweigen (= Hinzufügen von Elementen) lässt sich grafisch erledigen. Jedoch ist es ratsam, sich zumindest das Grundgerüst der DTD mit einem Texteditor zu überlegen.

Bild: 4  Abbildung einer DTD Struktur im Near&Far Designer
Ähnlich wie in Programmierumgebungen zählt aber schlussendlich, wie schnell man etwas in umfangreichen Quelltexten wiederfindet und anpassen / erweitern kann. Hier ist nach-wie-vor Plain-Text unschlagbar.
Deshalb ist es nicht verwunderlich, dass sich (wieder) leichtgewichtige Validierunsformate etablieren, die sich schön mit einem Texteditor editieren lassen, wie z.B. RelaxNG. RelaxNG existiert zwar schon seit 2002, erfreut sich aber in letzter Zeit zunehmender Beliebtheit.
Die Kompaktform der Regeln von RelaxNG sieht ein bisschen aus, wie JSON - was gerade für Webentwickler interessant sein könnte. Zudem wird die zugrunde liegende Logik der Backus-Naur Form ↗↗ relativ klar herausgestellt, was die Regelfindung erleichtert.
Um einen ersten Eindruck von der Syntax zu bekommen, habe ich mal das erste Beispiel aus dem RelaxNG Tutorial ↗↗ gestolen:
Consider a simple XML representation of an email address book:
<addressBook>
    <card>
        <name>John Smith</name>
        <email>js@example.com</email>
    </card>
    <card>
        <name>Fred Bloggs</name>
        <email>fb@example.net</email>
    </card>
</addressBook>
The DTD would be as follows:
<!DOCTYPE addressBook [
<!ELEMENT addressBook (card*)>
<!ELEMENT card (name, email)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT email (#PCDATA)>
]>
A RELAX NG pattern for this could be written as follows:
<element name="addressBook" xmlns="http://relaxng.org/ns/structure/1.0">
    <zeroOrMore>
        <element name="card">
            <element name="name">
                <text/>
            </element>
            <element name="email">
                <text/>
            </element>
        </element>
    </zeroOrMore>
</element>
In der Kurzform würde dieses Beispiel so aussehen:
element addressBook {
    element card {
        element name { text },
        element email { text }
    }*
}
Hinweis
NOTIZ
Schemadateien, die in der Kurzform verfasst sind, tragen gewöhnlicherweise die Dateiendung .rnc . Dateien in der Langform haben die Endung .rng .
Mit RelaxNG kann man Schema-Grammatiken fast so elegant wie mit der Backus Naur Normalform - BNF ↗↗modellieren - wie man das im Informatik Unterricht gelernt hat.

3.4.1  Exklusion mit RNC

Das schöne an RelaxNG ist die Tatsache, dass man damit Sachen machen kann, die mit anderen Schemasprachen nicht so leicht gehen. Z.b. kann man ein unvollständiges Schema erzeugen, das nur ganz bestimmte Teile der XML Instanz prüft.
Betrachten wir dazu das folgendes Beispiel:
unbehandeltesElement =
    element * - (aussteller | 
                 empfaenger |
                 datum) {
        (attribute * { text } | 
         text | 
         unbehandelteElemente)*
    }

start =
    element abrechung {
        element id { xsd:NMTOKEN },
        element datum  { xsd:date },
        [...]
        element zahlungen {
            element zahlung {
                element id { xsd:NMTOKEN },
                element datum  { xsd:date },
                element plan { xsd:NMTOKEN },
                [...]
            },
            element beleg-daten {
                element beleg {
                    attribute nummer { xsd:integer }?,
                    element datum  { xsd:date },
                    unbehandeltesElement+,
                    element aussteller { text },
                    unbehandeltesElement+,
                    element empfaenger { text },
                    unbehandeltesElement+
                }
            }
        }+
    }
}
Von den Elementen abrechnung und zahlung wissen wir, wie sie aufgebaut sind und können sie vollständig modellieren. Die unbekannte Größe ist allerdings das Element beleg . Dieses stammt von einer externen Quelle, und wir wissen nur, das darin zwingend die Felder datum , empfaenger und aussteller vorhanden sein müssen.
Zwischen diesen Elementen gibt es mindestens ein, aber auch mehrere unbekannte Elemente. Damit wir nun XML Instanzen, die nach diesem Schema aufgebaut sind, validieren können, wird ein Element unbehandeltesElement modelliert, das sozusagen einen Platzhalter darstellt. Dieses schliesst explizit die zwingenden Felder datum , empfaenger und aussteller aus, um deren Validierung durch das Schema nicht zu verfälschen.

3.4.2  Relaxtron

Besonders fortschrittlich klingt die Möglichkeit in ein RelaxNG Schema weitere Schematron-Regeln einzubinden - Relaxtron ↗↗. Damit kann man bspw. sicherstellen, dass bestimmte Constraints bzgl. der Elementstruktur eingehalten werden. Mit einer Schemasprache allein ginge das nicht. Betrachten wir das folgende Stück RelaxNG in der Kompaktform:
namespace sch = "http://purl.oclc.org/dsdl/schematron"

start = ul 
ul =
  [ 
    sch:pattern [
      sch:rule [
      context = "list"
        sch:assert [
          test = "not(ancestor::ul and ancestor::procedure)"
                 'Eine ul darf in der Procedure nicht verschachtelt werden!'
          ]
        ]
      ]
    ]
  element ul {
    any_attribute*, 
    listitem+
  }
  
listitem =
  element listitem {
    any_attribute*, 
    ( para | ul )+
  }

para =
  element para {
    any_attribute*, 
    text*
  }
any_attribute = attribute * { text }
Hier wird sichergestellt, dass eine ungeordnete Liste list nicht tiefer verschachtelt wird - aber nur innerhalb einer procedure .
Der oXygen Editor kann die RelaxNG Kopaktform in die XML Form überführen und schön visualisieren. Das sieht dann so aus:
Im oXygen Editor gibt es eine Vollmodell-Ansicht und eine Logische Modellansicht für RelaxNG Schemas, die auch eingebettete Schematron-Knoten anzeigen. Mit Klick auf ein Symbol gelangt man zum betreffenden Quelltextstück.

Bild: 5  Anzeige eines RelaxNG Schemas im oXygen Editor

3.4.3  Angabe des Schemas in der XML Instanz

Wie auch schon im Kapitel Anwendungsgebiete beschrieben, werden alle zusätzlichen - für den XML Prozessor wichtigen - Instruktionen, die nicht Teil der Daten sind, über eine Processing Instruction in das XML eingebunden.
Es können auch mehrere Schemata mittels einer Processing Instruction eingebunden werden, so dass eine Validierung über mehrere Engines möglich ist.
Übernimmt man bspw. einen Legacy Datenbestand, für den nur eine DTD vorhanden ist, so kann im Nachhinhein auch noch ein XML Schema hinzugefügt werden, welches komplexere semantische Beziehungen überprüft.
Für eine weitere Überprüfung steht schliesslich Schematron, vgl. Kapitel Validierung mit Schematron zur Verfügung. Ein Beispiel, wie man mehrere Schemas angibt, findet sich auf der Seite des W3 Konsortiums zum Thema ↗↗
<?xml version="1.0"?>
<?xml-model href="http://www.docbook.org/xml/5.0/rng/docbook.rng"?>
<?xml-model href="http://www.docbook.org/xml/5.0/xsd/docbook.xsd"?>
<book xmlns="http://docbook.org/ns/docbook">
  [...]
</book>
Zum Einbinden einer RelaxNG Kompaktform genügt es bspw. diese PI (Processing Instruction) anzugeben
<?xml-model href="whatever.rnc" type="application/relax-ng-compact-syntax"?>
oXygen und auch alle anderen Editoren unterstützen die Angabe des Schemas mittels PI, so dass man auch im Editor ohne explizite Anfrage validieren kann.

3.4.4  oXygen Validierung

Die Validierungswerkzeuge finden sich im oXygen Editor unter Document > Validate > Validate With
Über das Document Tab findet man in oXygen die Validierungsoptionen.

Bild: 6  Validierungsdialog in oXygen
Es lassen sich mit oXygen auch Schemas konvertieren, Document > Schema > Generate/Convert Schema
Tools zur Konvertierung sind ebenfalls im Document Tab untergebracht

Bild: 7  Schema-Konvertierung mit oXygen

3.4.5  Jing und Trang

Für RelaxNG gibt es den Jing Validator ↗↗. Bemerkenswert ist hier, dass das Tool von James Clark ↗↗ entwickelt wird (ein Urgestein in der XML Datenwelt).
VORSICHT!
Passt zwar nicht ganz zum Thema: Ein Tool von James Clark, mit dem ich schon öfters gearbeitet habe, ist SP ↗↗ ein SGML System, mit dem man SGML nach XML konvertieren kann. Diese Funktionalität ist wohl sonst eher selten zu finden ...
Um eine XML Instanz mit Jing zu validieren genügt folgender Kommandozeilenaufruf:
jing resources/schemas/person.rng resources/examples/person.xml
GEFAHR!
Jing unterstützt nicht die RelaxNG Kompaktform!
Die Kompaktform muss zuerst in die Normalform mit Trang ↗↗ konvertiert werden.
Um die Kompaktform von RelaxNG in die Normalform zu konvertieren setzt man diesen Befehl auf der Kommandozeile ab:
trang -I rnc -O rng resources/schemas/person.rnc resources/schemas/person.rng

3.4.6  Schema Single-Sourcing

Das Single-Sourcing Konzept macht auch vor Schemata nicht halt. Aus einer Quelle in der RelaxNG Kompaktform können alternative Ansichten in anderen Schema-Sprachen erzeugt werden, wie bspw. XML Schema (XSD) ↗↗.
Mit einem BPMN Diagramm kann man das Single-Sourcing Konzept bei der Schema-Erzeugung recht gut veranschaulichen. Aus einer RNC Quelle wird die RelaxNG XML Form, die Schematron-Regeln, die XSD und das XSLT der Schematron-Regeln generiert. Diese Artefakte dienen zur Validierung im Editor und zur Validierung in einer Transformer-Pipe.

Bild: 8  BPMN Diagramm zum Single-Sourcing Konzept bei RelaxNG Schemas
Ein Shell-Skript, das den Prozess aufruft, könnte z.B. so aussehen:
#!/bin/sh

echo "converting from RelaxNG compact form to RelaxNG XML form..."
trang -I rnc -O rng test.rnc test.rng 

echo "extracting embedded schematron rules from RelaxNG schema..." 
saxon -s:test.rng -o:test.sch -xsl:rng2sch.xsl

echo "converting RelaxNG schema to XML Schema..."
trang -O xsd test.rng test.xsd

echo "converting schematron rules to XSLT..."
saxon test.sch validation/schematron/iso_dsdl_include.xsl | \
saxon -s:- validation/schematron/iso_abstract_expand.xsl | \
saxon -s:- validation/schematron/iso_svrl_for_xslt2.xsl > test.xsl

echo "Done!"
Ein unpoliertes Skript zum Extrahieren der Schematron Regeln aus der RNC habe ich auf Github gefunden ↗↗.
Previous Page Next Page
Version: 93
Jan 25 2021