0

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

Marc
  • 174
  • 4
  • 12

2 Answers2

1

Here is a Schematron sample making use of XPath 2.0 expressions:

<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2"
    xmlns:sqf="http://www.schematron-quickfix.com/validator/process">

    <sch:title>Occurence</sch:title>

    <sch:let name="max-count" value="4"/>

    <sch:pattern id="occurence-test">
        <sch:rule context="/Root/ELEMENT">
            <sch:assert test="every $eid in Equipement/EqID satisfies count(Location/Sensor/EqID[. = $eid]) le $max-count">No more than <sch:value-of select="$max-count"/> references</sch:assert>         
        </sch:rule>
    </sch:pattern>
</sch:schema>

For a sample file

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="test2016051801.sch" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<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>
        <Equipement>
            <EqID>1</EqID>
        </Equipement>
        <Location>
            <Sensor>
                <EqID>1</EqID>
            </Sensor>
            <Sensor>
                <EqID>1</EqID>
            </Sensor>
            <Sensor>
                <EqID>1</EqID>
            </Sensor>
            <Sensor>
                <EqID>1</EqID>
            </Sensor>
            <Sensor>
                <EqID>1</EqID>
            </Sensor>
        </Location>
    </ELEMENT>
</Root>

you will get the error message No more than 4 references for the second ELEMENT element.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • Thanks for this answer. It seems correct but it does not solve my issue: We have to validate the same file on linux (my part) and excel (some else). In linux i could install saxon and use xslt 2.0 but it is not possible to do so in excel. Do you have a solution using xslt 1.0? Of course if i can write one i'll post it :) – Marc May 19 '16 at 12:23
0

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

Marc
  • 174
  • 4
  • 12