I am using Schematron to do some business rule validations. My xml data looks like:
<labtests>
<test>
<observation>
<code code="TT900" name="NMCK"/>
<outcome value="074042"/>
</observation>
</test>
<test>
<observation>
<code code="TT500" name="LVCT"/>
<outcome value="852417"/>
</observation>
</test>
<test>
<observation>
<code code="TT500" name="LVCT"/>
<outcome value="36542"/>
</observation>
</test>
<test>
<observation>
<code code="TT100" name="GVMC"/>
<outcome value="874541"/>
</observation>
</test>
<test>
<observation>
<code code="TT500" name="LVCT"/>
<outcome value="369521"/>
</observation>
</test>
</labtests>
The current context is set to labtests/test/observation
like below:
<iso:rule context="labtests/test/observation">
<!--perform all validations here-->
</iso:rule>
I want to perform some special business validation checks on the <outcome>
node for the first <observation>
block having code/@code="TT500"
.
I think I can use the following expression to get the position of first intended <observation>
block
count(../../test/observation/code[@code="TT500"]/preceding-sibling::*)+1
but I don't know how to compare this position with the node in the current context to perform special validation.
UPDATE:
For the sake of simplicity let's assume that the special validation to be performed in this case is that the length of outcome/@value
must be greater than or equal to 6. i.e.
<iso:report test="not(string-length(outcome/@value) >= 6">
outcome/@value should have at least 6 characters for the first TT500 observation
</iso:report>
The following Schematron document does exactly what you have asked. There is no real difference between assert
and report
, you can invert any rule to fit both.
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
<pattern>
<rule context="observation[code/@code = 'TT500' and not(preceding::observation[code/@code = 'TT500'])]">
<assert test="string-length(outcome/@value) ge 6"> outcome/@value should have at least 6 characters for the first TT500 observation </assert>
</rule>
</pattern>
</schema>
When the following (invalid) XML document is validated with this SCH rule:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="sample.sch" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<labtests>
<test>
<observation>
<code code="TT900" name="NMCK"/>
<outcome value="07442"/>
</observation>
</test>
<test>
<observation>
<code code="TT500" name="LVCT"/>
<outcome value="85417"/>
</observation>
</test>
<test>
<observation>
<code code="TT500" name="LVCT"/>
<outcome value="36542"/>
</observation>
</test>
</labtests>
A Schematron processor will issue a warning along the lines of
E [ISO Schematron] outcome/@value should have at least 6 characters for the first TT500 observation