Solution

<schema xmlns="http://purl.oclc.org/dsdl/schematron">
  <ns uri="http://www.schematron.info/arche" prefix="ark"/>
  <pattern>                                                   (1)
    <rule context="ark:animal[@sex='male']">                  (1a)
      <report test="number(ark:age) &gt; number(//ark:maxReproductionAge/ark:animal_species[ark:name=current()/ark:species]/ark:male)"> (1b)
      The male is too old, Noah! It is probably no longer able to reproduce.
      You have to enforce the natural selection.</report>
    </rule>
    <rule context="ark:animal[@sex='female']">                (1a)
      <report test="number(ark:age) &gt; number(//ark:maxReproductionAge/ark:animal_species[ark:name=current()/ark:species]/ark:female)"> (1b)
      The female is too old, Noah! It is probably no longer able to reproduce.
      You have to enforce the natural selection.</report>
    </rule>
  </pattern>
 
  <pattern>
    <rule context="ark:loadingCapacity">                       (2)
      <report test=". &lt; sum(//ark:weight)">                 (2a)
      Noah, there are too many animals on board. 
      The load exceeds the loading capacity of your Ark.</report>
    </rule>
  </pattern>
 
  <pattern>                                                    (3)
    <rule context="ark:animal[@carnivore='yes']">
      <report test="parent::*/ark:animal[@carnivore='no']">
      There are carnivores and herbivores in one accommodation. 
      The animals are not a food source!</report>
      <report test="parent::*/ark:animal/ark:weight &lt; (ark:weight div 2)">
      Noah, this carnivore is too strong (heavy) for its roommate.
      The carnivore could use it as a food source.</report>
    </rule>
    <rule context="ark:animal">
      <report test="parent::*/ark:animal/ark:weight &lt; (ark:weight div 10)">
      Noah, the animal is too heavy for its rommates! 
      It could trample down one of them.</report>
    </rule>
  </pattern>
 
  <pattern>
    <rule context="ark:animal">                                                             (4)
      <report test="count(//ark:animal[ark:species=current()/ark:species]) &gt; 2">         (4a)
      There are more than two animals of this species on the Ark.</report>
      <report test="count(parent::*/ark:animal[ark:species=current()/ark:species]) &lt; 2"> (4b)
      There are less than two animals of this species in this accommodation.
      </report>
      <assert test="count(parent::*/ark:animal[ark:species=current()/ark:species][@sex='male'])=1"> (4c)
      A pair must always consist of one male and one female.
      </assert>
    </rule>
  </pattern>
 
  <pattern>
    <rule context="ark:room">                                       (5)
      <report test="count(ark:animal) &gt; 6">
      Noah, if you accommodate too many animals in the same room, it could have a 
      negative effect on the room community! You should not accommodate 
      more than 6 animals in one room.
      </report>
    </rule>
  </pattern>
</schema>
(1) Regarding the reproduction age, a distinction must be made between the male and the female animals since the maximum reproduction age for male animals is indicated in the <male> elements and for female animals in the <female> elements.
(a) The context node is set to the <animal> element since for each animal the age has to be checked.
(b) The tests being defined in this example compare the respective age of the animals with the appropriate age from the <maxReproductionAge> container. For this purpose, the <animal_species> element is selected containing a <name> element which corresponds to the <species> element of the context node. Now, in the appropriate <animal_species> element the maximum reproduction age is either taken from the <male> or from the <female> element. Since here no data type has been determined, but two numbers shall be compared, both have to be transformed into a numerical value by the number() function.
 
(2) The loading capacity is indicated in the <loadingCapacity> element. The compliance with the loading capacity has only to be checked once, which is why the <loadingCapacity> element has been selected as a context node.
(a) For this test all <weight> elements of the document are added up and it is checked whether the sum is smaller than the value of <loadingCapacity>.
 
(3) This pattern has already been discussed in detail.
(4) This rule checks for each animal with a combination of three tests that no more than one pair of a species is on the Ark, the pair is accommodated in the same room and consists of one male and one female.
(a) This test counts (with the count() function) all animals which contain the same <species> element as the context node. The test is formulated in such a way that the result must not be greater than two. In this way, the test ensures that a maximum of two animals of a species has been accommodated on the Ark.
(b) The second test checks whether at least two animals of a species are accommodated in the same room. Since the previous test already checks that no more than two animals of a species can be found on the entire Ark, the combination of both tests results in the condition that exactly one pair has to be accommodated in the same room.
(c) For the third test a condition is used which checks in combination with the other tests whether the pair consists of a male and a female or not.
 
(5) This rule checks all <room> elements. The test counts for each room the number of animals and checks whether more than six <animal> elements are contained.
<< back>> to the Schematron reference

 

 

 

 


Copyright © dpunkt.verlag GmbH 2011
Printing of the online version is permitted exclusively for private use. Otherwise this chapter from the book "Schematron - Effiziente Business Rules für XML-Dokumente" is subject to the same provisions as those applicable for the hardcover edition: The work including all its components is protected by copyright. All rights reserved, including reproduction, translation, microfilming as well as storage and processing in electronic systems.

dpunkt.verlag GmbH, Ringstraße 19B, 69115 Heidelberg, fon 06221-14830, fax 06221-148399, hallo(at)dpunkt.de