Schematron bietet eine differenzierte Logik, um Tests zu organisieren. Dafür werden die hierarchisch organisierten Elemente pattern
, rule
sowie assert
bzw. report
verwendet. Mit phase
gibt es eine Möglichkeit, einzelne oder mehrere pattern
und damit nur Teile des Schemas zur Validierung zu verwenden.
Die eigentlichen Tests werden mit assert
und report
auf der untersten Hierarchiestufe definiert. report
gibt einen Fehler aus, wenn der Ausdruck im test
-Attribute wahr
wird, assert
hingegen, wenn der Ausdruck nicht erfüllt ist. Außer diesem Unterschied funktionieren beide Elemente exakt gleich; dass es beide gibt, macht Schemata übersichtlicher.
assert
und report
stehen innerhalb von rule
. Dieses Element dient hauptsächlich dazu, den Kontext für die enthaltenen assert
und report
zu bestimmen. Achtung! Stehen mehrere rule
mit identischem Kontext innerhalb eines pattern
, wird nur die erste rule
berücksichtigt, weitere rule
werden ignoriert. Meist wird man statt mehrerer rule
mit identischem Kontext eine rule
mit mehreren assert
bzw. report
verwenden können, falls nicht, müssen getrennte pattern
mit diesen rule
geschrieben werden.
pattern
fassen eine oder mehrere rule
zusammen. Außerdem dienen sie zur Entkopplung mehrerer rule
mit identischem Kontext (s.o.). Eine besondere Bedeutung erlangen sie im Zusammenhang mit phase
. Innerhalb von phase
-Elementen werden einzelne pattern
referenziert und damit verschiedene Validierungsumfänge definiert.
An Hand eines einfachen Beispiels möchte ich das erläutern. In einem Literaturverzeichnis sind Bücher gelistet:
<literatur> <buecher> <buch xml:id="b1"> <autor ref="p1">Mann, Thomas</autor> <titel>Der Zauberberg</titel> </buch> <buch xml:id="b3"> <autor ref="b1"></autor> <titel></titel> </buch> </buecher> </literatur> |
autor
– und titel
-Elemente sollen nicht leer sein. Das entsprechende Schema sieht so aus:
<schema xmlns="http://purl.oclc.org/dsdl/schematron" > <pattern id="p1"> <rule context="buch"> <assert test="normalize-space(autor)">[p1] autor darf nicht leer sein</assert> <assert test="normalize-space(titel)">[p1] titel darf nicht leer sein</assert> </rule> </pattern> <pattern id="p2"> <rule context="buch"> <assert test="normalize-space(autor)">[p2] autor darf nicht leer sein</assert> </rule> <rule context="buch"> <assert test="normalize-space(titel)">[p2] titel darf nicht leer sein</assert> </rule> </pattern> <phase id="phase_1"> <active pattern="p1"/> </phase> <phase id="phase_2"> <active pattern="p2"/> </phase> </schema> |
Schauen wir zuerst auf pattern id="p1"
. Im rule
-Element wird der Kontext auf alle buch
-Elemente gesetzt und dann mit zwei nahezu identischen assert
geprüft, ob die Elemente autor
und titel
Text enthalten (wobei Text, der ausschließlich aus Leerzeichen, Tabs u.ä. – kurz whitespace – besteht, mit normalize-space()
entfernt wird).
pattern id="p2"
demonstriert, dass bei mehreren rule
mit identischem Kontext nur das erste rule
ausgewertet wird: während bei p1
zwei Fehler gemeldet werden (autor
und titel
ohne Text bei b3
), wird von p2
nur der erste Fehler gemeldet.
Die beiden phase
-Elemete demonstrieren, wie man ein Schema logisch aufteilen kann. Per default (und ohne Eintrag im defaultPhase
-Attribut im äußersten schema
-Element) werden alle pattern
validiert. Wenn mit phase
-Elementen verschiedene Phasen definiert werden, könne diese getrennt ausgeführt werden. Beispielsweise fragt OxygenXML dann nach, welche Phase validiert werden soll, vgl. Bild rechts.
XML-Beispiel und Schematron sind in der Beispielsammlung abgelegt.
Weblink
- Dave Pawson, Roger Costello, Florent Georges: ISO Schematron tutorial. Getting Started (englisch)