Archiv für April, 2012

Schematron: Wie werden assert/report, rule, pattern und phase verwendet?

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.

Auswahldialog für Phasen in OxygenXMLDie 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)

»crosslinked«

Keine Kommentare