Search code examples
xmlxsltxpathschematron

Schematron validating count of element value


Assume I have an XML document defining:

<Root>
  <ELEMENT>
    <Equipement>
      <EqID>1</EqID>
    </Equipement>
    <Equipement>
      <EqID>2</EqID>
    </Equipement>


    <Location>
      <Sensor>
        <EqID>2</EqID>
      </Sensor>
      <Sensor>
        <EqID>2</EqID>
      </Sensor>
    </Location>


    <Location>
      <Sensor>
        <EqID>1</EqID>
      </Sensor>
      <Sensor>
        <EqID>2</EqID>
      </Sensor>
    </Location>
  </ELEMENT>
  <ELEMENT>
   ...
  </ELEMENT>
</Root>

I want to validate that in the context of each < ELEMENT >, each of its Equipement/EqID is referenced by a maximum of 4 Location/Sensor/EqID. In this example it is OK because EqID '2' is referenced 3 times and EqId '1' is referenced only once.

Each < ELEMENT > is treated independantly.

I am not very familiar with schematron and xsl so i am not even sure it can be done!

Thanks

EDIT: Thanks martin for a solution usint XSLT 2.0 but in my context i am forced to used XSLT 1.0.

EDIT2: I posted a XSTL 1.0 solution bellow


Solution

  • Here is a solution using xslt 1.0

    <sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron">
        <sch:title>Occurence</sch:title>
        <sch:let name="max-count" value="4"/>
        <sch:pattern id="occurence-test">
    
            <sch:rule context="/Root/ELEMENT/Equipement">
              <sch:let name="eqid" value="EqID"/>
              <sch:assert test="count(parent::*/Location/Sensor[EqID = $eqid])  &lt;= $max-count">EqID <sch:value-of select="$eqid"/> is referenced <sch:value-of select="count(parent::*/Location/Sensor[EqID = $eqid])"/> times. No more than <sch:value-of select="$max-count"/> references</sch:assert>
            </sch:rule>
        </sch:pattern>
    </sch:schema>
    

    With Martin's sample file it produces the expected output

    <svrl:failed-assert test="count(parent::*/Location/Sensor[EqID = $eqid]) &lt;= $max-count" location="/Root/ELEMENT[2]/Equipement">
    <svrl:text>EqID 1 is referenced 5 times. No more than 4 references</svrl:text>
    </svrl:failed-assert>
    

    Any improvement/suggestion/comment would be appreciated Marc