Disposición de las plantillas

Hasta ahora hemos presentado sólo esquemas Schematron que contienen una sola regla. Para la aplicación de varias reglas se utiliza el elemento <pattern>, que ahora trataremos con más profundidad.

Disposición incorrecta de las reglas

En la mayoría de los casos es posible renunciar a una disposición especial y anidar cada regla en su propio elemento <pattern>. De esta manera los elementos <pattern> se sucederán uno tras otro y las reglas contenidas en los mismos tendrán la misma prioridad. Además, al igual que ocurre con la disposición de los tests, no existen diferencias funcionales que dependan del orden de las reglas en el esquema.
No obstante, anidar varias reglas en un elemento <pattern> puede incrementar el rendimiento del esquema. Por otra parte, con la práctica y mediante una apropiada comprobación de errores, es posible utilizar una disposición bien estudiada de las reglas en las plantillas con fines funcionales. Sin embargo, aquí nos centraremos en primer lugar en posibles disposiciones incorrectas de las reglas:

<pattern>
  <rule context="arc:animal[@fleischfresser='ja']">
    <report test="parent::*/arc:animal[@carnivoro='no']">
    Hay animales carnívoros y herbívoros en un mismo compartimento. 
    ¡Los animales no pueden ser utilizados como fuente de comida!
    </report>
    <report test="parent::*/arc:animal/arc:peso &lt; (arc:peso div 2)">
    Noé, este animal carnívoro es muy fuerte para su compañero. 
    Podría usarlo como fuente de comida.
    </report>
  </rule>
  <rule context="arc:animal">
    <report test="count (parent::*/arc:animal[arc:especie=current()/arc:especie]) &lt; 2">
    En este compartimento hay menos de dos animales de esta especie.
    </report>
  </rule>
</pattern>

Básicamente no hay errores en esta plantilla. Una plantilla puede componerse de varias reglas. No obstante, se debe tener en cuenta que en el análisis es importante el orden de las reglas dentro de una plantlla.

 

Aquí se aplicará el siguiente principio:
Dentro de una plantilla se podrá seleccionar cada nodo de la instancia sólo una vez como nodo de contexto de una regla. En caso de que un nodo cumpla una condición impuesta en "context" y que esta sea aplicable a varias reglas, este nodo sólo se seleccionará como nodo de contexto para la primera regla que sea válida. Para comprender mejor este principio, podemos imaginarnos que cada regla dentro de una plantilla es una criba. Las cribas se disponen una encima de otra en el mismo orden que las reglas de la plantilla, de manera que los nodos de la instancia se pueden verter como un chorro de arena a través de los mismos. Cuando una regla es aplicable a un nodo, ésta no lo dejará pasar. Es como si el nodo encajase en una criba y no pudiese atravesarla, de manera que no pasará a la siguente criba. El nodo queda pues excluido para todas las cribas siguientes.

 

¿Qué significa esto para la plantilla de nuestro ejemplo?
Examinemos en primer lugar cada una de las reglas. La primera de ellas ya la conocemos, con esta regla seleccionamos todos los carnívoros y comprobamos si el respectivo elemento padre <compartimento> contiene un animal que no sea carnívoro, o bien, un animal que pudiera estar en peligro.
La segunda regla selecciona todos los animales y sirve para asegurar que el elemento padre no contiene más de dos animales de la misma especie (incluido el animal seleccionado).
Sin embargo, si tenemos en cuenta el principio mencionado más arriba, según el cual se muestra la importancia del orden de las reglas en una plantilla, podemos comprobar que la segunda regla no será ejecutada. Puesto que la primera regla selecciona todos los carnívoros como nodos de contexto, la segunda regla sólo verificará los nodos con animales herbívoros, pero esto no es lo que se persigue con la regla. Si queremos que se verifique para todos los animales si existe más de una pareja en un compartimento, debemos anidar la regla en una plantilla independiente:

<pattern>
  <rule context="arc:animal[@carnivoro='sí']">
    <report test="parent::*/arc:animal[@carnivoro='no']">
    Hay animales carnívoros y herbívoros en un mismo compartimento. 
    ¡Los animales no pueden ser utilizados como fuente de comida!
    </report>
    <report test="parent::*/arc:animal/arc:peso &lt; (arc:peso div 2)">
    Noé, este animal carnívoro es muy fuerte para su compañero. 
    Podría usarlo como fuente de comida.
    </report>
  </rule>
</pattern>
<pattern>
  <rule context="arc:animal">
    <report test="count(parent::*/arc:animal[arc:especie=current()/arc:especie]) &lt; 2">
    En este compartimento hay menos de dos animales de esta especie.
    </report>
  </rule>
</pattern>

Derechos de autor © dpunkt.verlag GmbH 2011
El usuario podrá imprimir la versión online. La copia será exclusivamente para uso personal. Por lo demás el presente capítulo del libro publicado en lengua alemana "Schematron - Effiziente Business Rules für XML-Dokumente" está sometido a los mismos términos y condiciones que la versión impresa. La presente obra está protegida en su totalidad por la ley de propiedad intelectual. Reservados todos los derechos, incluyendo los derechos de reproducción, traducción, microfilmación, así como el almacenamiento y procesamiento en sistemas electrónicos.

dpunkt.verlag GmbH, Ringstraße 19B, 69115 Heidelberg, teléfono + 49 (0) 6221 14830, fax + 49 (0) 6221 148399, hallo(at)dpunkt.de