• Aucun résultat trouvé

7. Schematron

7.7. Blocs abstraits

Les blocs abstraits généralisent le principe des règles abstraites. Ils déclarent des règles qui peuvent s'appliquer à différentes situations. Leur principe de fonctionnement est proche de celui des fonctions de n'importe quel langage de programmation. Un bloc abstrait contient des règles qui utilisent des paramètres. Ce bloc est alors utilisé par d'autres blocs qui instancient les paramètres en leur donnant des valeurs explicites.

Un bloc est déclaré abstrait avec un attribut abstract ayant la valeur true. Le bloc qui utilise un bloc abstrait doit avoir un attribut is-a qui donne l'identifiant du bloc abstrait. Il ne doit pas contenir de règles mais seulement des éléments sch:param qui permettent d'instancier les paramètres. L'élément sch:param a des attributs name et value qui donnent respectivement le nom du paramètre et la valeur qui lui est affectée.

Le fonctionnement des blocs abstraits est semblable au passage de paramètres des éléments xsl:apply-templates et xsl:call-template [Section 8.9.2] de XSLT. En revanche, l'élément sch:param des

Schematron

schematrons est l'analogue de l'élément xsl:with-param de XSLT. L'élément xsl:param de XSLT n'a pas d'équivalent dans les schematrons car les paramètres des blocs abstraits ne sont pas déclarés.

Le schematron suivant définit un bloc abstrait uniq qui contient deux règles dépendant des paramètres elem et desc. La première règle vérifie que l'élément elem a au moins un descendant desc. La seconde vérifie au contraire qu'il n'a pas plus d'un descendant desc. Ces deux règles conjuguées vérifient donc que l'élément elem a exactement un seul descendant desc.

Le bloc abstrait uniq est ensuite utilisé par les deux blocs uniq-id et uniq-title. Le premier bloc donne les valeurs book et @id|@key aux deux paramètres elem et desc. Il vérifie donc que chaque élément book possède exactement un seul des deux attributs id et key. Le second bloc donne les valeurs book et title aux paramètres elem et desc. Il vérifie donc que chaque élément book possède exactement un seul enfant title.

La vérification effectuée par le premier bloc n'est pas faisable avec les DTD [Chapitre 3] et les schémas XML [Chapitre 5]. Les déclarations d'attributs de ces deux langages se font sur chacun des attributs de façon indépendante. Il n'est pas possible d'exprimer une contrainte qui met en relation deux attributs ou deux éléments.

<?xml version="1.0" encoding="utf-8"?>

<sch:schema queryBinding="xslt" schemaVersion="ISO19757-3"

xmlns:sch="http://purl.oclc.org/dsdl/schematron">

<sch:title>Utilisation de blocs abtraits</sch:title>

<!-- Déclaration du bloc abstrait -->

<sch:pattern abstract="true" id="uniq">

<!-- Les règles utilisent les paramètres elem et desc -->

<sch:rule context="$elem">

<sch:assert test="$desc">

L'élément <sch:name/> doit avoir un descendant $desc.

</sch:assert>

<sch:report test="count($desc) &gt; 1">

L'élément <sch:name/> doit avoir un seul descendant $desc.

</sch:report>

</sch:rule>

</sch:pattern>

<!-- Utilisation du bloc abstrait -->

<sch:pattern is-a="uniq" id="uniq-id">

<sch:param name="elem" value="book"/>

<sch:param name="desc" value="@id|@key"/>

</sch:pattern>

<sch:pattern is-a="uniq" id="uniq-title">

<sch:param name="elem" value="book"/>

<sch:param name="desc" value="title"/>

</sch:pattern>

</sch:schema>

Le mécanisme des blocs abstraits est souvent implémenté comme les #define du langage C. Chaque bloc qui utilise un bloc abstrait est remplacé par une copie de celui-ci où les paramètres sont substitués par leurs valeurs.

Le schematron précédent est en fait équivalent au schematron suivant. Le bloc abstrait uniq a disparu mais ses règles apparaissent dupliquées dans les deux blocs uniq-id et uniq-title.

<?xml version="1.0" encoding="utf-8"?>

<sch:schema queryBinding="xslt" schemaVersion="ISO19757-3"

xmlns:sch="http://purl.oclc.org/dsdl/schematron">

<sch:title>Substitution des blocs abstraits</sch:title>

<sch:pattern id="uniq-id">

<sch:rule context="book">

<sch:assert test="@id|@key">

L'élément <sch:name/> doit avoir un descendant @id|@key </sch:assert>

<sch:report test="count(@id|@key) &gt; 1">

Schematron

L'élément <sch:name/> doit avoir un seul descendant @id|@key </sch:report>

</sch:rule>

</sch:pattern>

<sch:pattern id="uniq-title">

<sch:rule context="book">

<sch:assert test="title">

L'élément <sch:name/> doit avoir un descendant title </sch:assert>

<sch:report test="count(title) &gt; 1">

L'élément <sch:name/> doit avoir un seul descendant title </sch:report>

</sch:rule>

</sch:pattern>

</sch:schema>

L'exemple ci-dessous illustre la puissance des schematrons. Ce schematron exprime certaines contraintes que doivent satisfaire les schematrons pour être valides. Ces contraintes portent sur les liens entre les éléments pattern abstraits et ceux qui les utilisent.

<?xml version="1.0" encoding="utf-8"?>

<sch:schema queryBinding="xslt" schemaVersion="ISO19757-3"

xmlns:sch="http://purl.oclc.org/dsdl/schematron"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<sch:title>Vérification des liens is-a des schematrons</sch:title>

<sch:p>Ce schematron vérifie que, dans un schematron, tout bloc référencé par un autre bloc par l'attribut is-a est bien déclaré abstrait par

l'attribut abstract avec la valeur true.</sch:p>

<!-- Déclaration de l'espace de noms cible : celui des schematrons -->

<!-- Ne pas utiliser le préfixe sch car cela pose problème -->

<sch:ns prefix="tns" uri="http://purl.oclc.org/dsdl/schematron"/>

<!-- Clé pour retrouver les éléments pattern par leur id -->

<xsl:key name="patid" match="tns:pattern" use="@id"/>

<sch:pattern>

<sch:rule context="tns:pattern[@is-a]">

<sch:assert test="key('patid', @is-a)">

L'attribut is-a doit référencer un bloc abstrait.

</sch:assert>

<sch:report test="@abstract = 'true'">

Un bloc avec un attribut is-a ne peut pas être abstrait.

</sch:report>

<sch:report test="rule">

Un bloc avec un attribut is-a ne peut pas contenir de règle.

</sch:report>

</sch:rule>

</sch:pattern>

<sch:pattern>

<sch:rule context="tns:pattern[@abstract = 'true']">

<sch:assert test="@id">

Un bloc abstrait doit avoir un attribut id.

</sch:assert>

<sch:report test="@is-a">

Un bloc abstrait ne peut pas avoir un attribut is-a.

</sch:report>

Schematron

</sch:rule>

</sch:pattern>

</sch:schema>