Testing Schematron with Text Nodes - xspec/xspec GitHub Wiki
This page pertains to XSpec v2.3.2 and earlier. When using v3.0.3 and later, you will not see the failures in the example below and do not need the workaround.
Suppose you have this Schematron schema containing <sch:rule context="text()">
:
test.sch
<sch:schema queryBinding="xslt2" xmlns:sch="http://purl.oclc.org/dsdl/schematron">
<sch:pattern>
<sch:rule context="text()">
<sch:report id="above-mentioned" role="info" test="matches(., 'above-mentioned')"
>Forbidden word: above-mentioned</sch:report>
</sch:rule>
</sch:pattern>
</sch:schema>
And suppose you test it with this XSpec:
test1.xspec
<x:description schematron="test.sch" xmlns:x="http://www.jenitennison.com/xslt/xspec">
<x:scenario focus="test this framework" label="above-mentioned">
<x:context>
<conbody>
<p>above-mentioned</p>
</conbody>
</x:context>
<x:expect-report id="above-mentioned" role="info" />
<x:expect-report id="above-mentioned" location="//text()[. eq 'above-mentioned']" role="info" />
</x:scenario>
</x:description>
Both of expect-report
tests fail:
C:\test>xspec.bat -s test1.xspec
...
report above-mentioned info
FAILED
report above-mentioned info //text()[. eq 'above-mentioned']
FAILED
...
passed: 0 / pending: 0 / failed: 2 / total: 2
They fail, because the skeleton Schematron implementation bundled into XSpec does not visit text nodes by default:
To make <sch:rule context="text()">
work, you need to tell the skeleton Schematron implementation to visit text nodes:
test2.xspec
<x:description schematron="test.sch" xmlns:x="http://www.jenitennison.com/xslt/xspec">
<x:param name="only-child-elements">false</x:param>
<x:param name="visit-text">true</x:param>
<x:scenario focus="test this framework" label="above-mentioned">
<x:context>
<conbody>
<p>above-mentioned</p>
</conbody>
</x:context>
<x:expect-report id="above-mentioned" role="info" />
<x:expect-report id="above-mentioned" location="//text()[. eq 'above-mentioned']" role="info" />
</x:scenario>
</x:description>
Note that this revised XSpec has two global parameters (/x:description/x:param
). They are passed to the Schematron implementation.
This time the skeleton Schematron implementation visits text nodes and the 1st expect-report
is now successful:
C:\test>xspec.bat -s test2.xspec
...
report above-mentioned info
report above-mentioned info //text()[. eq 'above-mentioned']
...
ERROR in svrl:successful-report/@location: Expression above-mentioned should point to one node.
*** Error running the test suite
The 2nd expect-report
generates a fatal error, because it has @location
and the skeleton Schematron implementation cannot handle @location
with text nodes. In this case, the skeleton Schematron implementation generates SVRL containing a broken svrl:successful-report/@location
.
To make @location
work with text nodes, you have to fix the skeleton Schematron implementation privately or use another implementation of Schematron.
Alternatively, use another implementation of Schematron, following instructions in Using SchXslt with XSpec v2.3.2 and earlier.
Also note that SchXslt visits text nodes by default, so you don't need to set global x:param
. With SchXslt, you can use test1.xspec
instead of test2.xspec
for this example.