Abstrakte Patterns
(Auszug aus "Schematron - Effiziente Business Rules für XML-Dokumente", Kapitel 7)
Neben abstrakten Regeln bietet Schematron auch die Verwendung von sogenannten abstrakten Patterns. Ein abstraktes Pattern kann von einem anderen Pattern aufgerufen bzw. instanziiert werden. Beim Aufruf wird eine Parameter-Liste übergeben. Auch hierzu bietet unser Arche-Schema ein Beispiel:
<rule context="arc:tier[@geschlecht='männlich']">
<report test="number(arc:alter) > number(//arc:maxReproduktionsalter/arc:tier_art[arc:name=current()/arc:art]/arc:männlich)">Das Männchen ist zu alt, Noah! Es wird sich nicht mehr fortpflanzen können. Sorge für die natürliche Auslese.</report>
</rule>
<rule context="arc:tier[@geschlecht='weiblich']">
<report test="number(arc:alter) > number(//arc:maxReproduktionsalter/arc:tier_art[arc:name=current()/arc:art]/arc:weiblich)">Das Weibchen ist zu alt, Noah! Es wird sich nicht mehr fortpflanzen können. Sorge für die natürliche Auslese.</report>
</rule>
Die beiden Regeln unterscheiden sich nur anhand der markierten Stellen. Da die beiden XPath-Tests auf unterschiedliche Elemente zugreifen, ist dieser Sachverhalt nicht so leicht mit Variablen zu lösen. Eine Möglichkeit gäbe es mit Hilfe der local-name()-Funktion. Eleganter können wir dies mit einem abstrakten Pattern gestalten. Zunächst erzeugen wir ein abstraktes Pattern, ohne entsprechenden Aufruf.
<pattern abstract="true" id="geschlecht"> (1)
<rule context="arc:tier[@geschlecht='$geschlecht']"> (2)
<report test="number(arc:alter) > number(//arc:maxReproduktionsalter/arc:tier_art[arc:name=current()/arc:art]/arc:$geschlecht)">Das Tier ist zu alt, Noah! Es wird sich nicht mehr fortpflanzen können. Sorge für die natürliche Auslese.</report> (3)
</rule>
</pattern>
(1) Einem Pattern wird ein abstract-Attribut mit dem Wert true hinzugefügt. Wie auch bei abstrakten Regeln ist nun ein id-Attribut nötig.
(2) Überall dort, wo sich die beiden Regeln in männlich/weiblich unterscheiden, wird auf einen Parameter $geschlecht zurückgegriffen, den wir bisher jedoch noch nicht definiert haben. Etwas verwirrend ist, dass der Aufruf des Parameters auf die gleiche Weise funktioniert wie der einer Variablen.
(3) Da wir nicht zwischen Männchen und Weibchen unterscheiden können, wird hier neutral Tier eingefügt.
Der Unterschied zur Variablen wird besonders im test-Attribut deutlich. Der Parameter wird von XPath nicht als Variable verwendet, sondern bevor der XPath-Ausdruck aufgelöst wird, werden per Suche-Ersetze-Anweisung alle Strings $geschlecht durch den Wert des Parameters (weiblich oder männlich) ersetzt. Erst dann wird überprüft, ob der Ausdruck der Syntax für XPath-Ausdrücke entspricht.
Dieses abstrakte Pattern wird bisher jedoch noch nicht verwendet und ist zurzeit somit noch gegenstandslos. Aktiv wird es erst, wenn es aufgerufen wird. Dies funktioniert mit einem weiteren <pattern>-Element. Bei dem Aufruf wird mit dem is-a-Attribut auf das abstrakte Pattern verwiesen und eine Liste an Parametern übergeben, die im aufgerufenen Pattern verwendet werden. Für jeden übergebenen Parameter wird ein <param>-Element mit dem entsprechenden Namen (name-Attribut) und Wert (value-Attribut) benötigt. Ein <pattern>-Element, das ein anderes Pattern aufruft, darf nur noch <param>-Elemente enthalten.
<pattern is-a="geschlecht"> (1)
<param name="geschlecht" value="männlich"/> (2)
</pattern>
<pattern is-a="geschlecht"> (1)
<param name="geschlecht" value="weiblich"/> (2)
</pattern>
<pattern abstract="true" id="geschlecht">
<rule context="arc:tier[@geschlecht='$geschlecht']"> (3)
<report test="number(arc:alter) > number(//arc:maxReproduktionsalter/arc:tier_art [arc:name=current()/arc:art]/arc:$geschlecht)">Das Tier ist zu alt, Noah! Es wird sich nicht mehr fortpflanzen können. Sorge für die natürliche Auslese.</report>
</rule>
</pattern>
(1) Die <pattern>-Elemente rufen mit dem is-a-Attribut jeweils das abstrakte Pattern auf. Als Wert wird hier die ID des abstrakten Patterns (geschlecht) angegeben. Das abstrakte Pattern wird hier zweimal aufgerufen – einmal für männliche und einmal für weibliche Tiere.
(2) In unserem Pattern wird $geschlecht als Parameter eingesetzt. Es wird somit ein <param>-Element pro konkretem Pattern erzeugt. Im Gegensatz zum <xsl:param>-Element von XSLT, wird hier im value-Attribut nicht mit einem XPath-Ausdruck der Wert des Parameters ermittelt, sondern die Zeichenkette des Attributwertes stellt den Parameterwert dar. Daher werden die Zeichenketten nicht in Hochkomma geschreiben (z.B. 'weiblich'), wie es bei einem XPath-Ausdruck notwendig wäre.
(3) Der Parameter-Aufruf $geschlecht wird nun vollständig durch die Zeichenkette, die dem Parameter zugewiesen wurde, ersetzt. Nach dem Ersetzen müssen die XPath-Ausdrücke syntaktisch korrekt sein.
Parameter können nur in XPath-Ausdrücken verwendet werden. Soll der Parameter auch die Fehlermeldung beeinflussen, muss der vom Parameter abhängige Text per <value-of>-Element eingefügt werden. Zu beachten ist, dass ein String in XPath in Hochkommata gestellt werden muss. Wir möchten nun statt Das Tier ist zu alt… die Strings Das männliche Tier ist zu alt… bzw. Das weibliche Tier ist zu alt... ausgeben. Wir müssen also entsprechende <value-of>-Elemente per Parameter generieren lassen.
<pattern is-a="geschlecht">
<param name="geschlecht" value="männlich"/>
</pattern>
<pattern is-a="geschlecht">
<param name="geschlecht" value="weiblich"/>
</pattern>
<pattern abstract="true" id="geschlecht">
<rule context="arc:tier[@geschlecht='$geschlecht']">
<report test="number(arc:alter) > number(//arc:maxReproduktionsalter/arc:tier_art[arc:name=current()/arc:art]/arc:$geschlecht)">Das <value-of select="'$geschlechte'"/> Tier ist zu alt, Noah! Es wird sich nicht mehr fortpflanzen können. Sorge für die natürliche Auslese.</report> (1)
</rule>
</pattern>
(1) Zu beachten ist, dass der Parameter-Aufruf hier scheinbar $geschlechte heißt. Das liegt daran, dass dem Parameter die Werte weiblich und männlich zugewiesen wurden, wir wollen aber mit dem <value-of>-Element die Strings männliche und weibliche erzeugen. Durch die Auflösung des Parameters nach dem Prinzip Suche-Ersetze wird aus den Werten des select-Attributs 'männliche' bzw. 'weibliche', da nur die Zeichenkette $geschlecht durch den jeweiligen Parameterwert ersetzt wird.
Auf diese Weise können mehrere Patterns, die sich nur an bestimmten Stellen unterscheiden, zu einem abstrakten Pattern kombiniert werden.
<< zurück | vor >> |
Tipp der data2type-Redaktion: Zum Thema Schematron bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an: |
Copyright © dpunkt.verlag GmbH 2011
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken. Ansonsten unterliegt dieses Kapitel aus dem Buch "Schematron - Effiziente Business Rules für XML-Dokumente" 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.
dpunkt.verlag GmbH, Ringstraße 19B, 69115 Heidelberg, fon 06221-14830, fax 06221-148399, hallo(at)dpunkt.de