1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.helger.schematron.pure;
18
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertTrue;
23
24 import java.nio.charset.StandardCharsets;
25 import java.util.List;
26
27 import javax.xml.validation.Schema;
28
29 import org.junit.Test;
30 import org.oclc.purl.dsdl.svrl.SchematronOutputType;
31 import org.w3c.dom.Document;
32 import org.w3c.dom.Node;
33
34 import com.helger.commons.io.resource.ClassPathResource;
35 import com.helger.commons.io.resource.IReadableResource;
36 import com.helger.commons.io.stream.StringInputStream;
37 import com.helger.schematron.SchematronException;
38 import com.helger.schematron.pure.errorhandler.CollectingPSErrorHandler;
39 import com.helger.schematron.pure.errorhandler.DoNothingPSErrorHandler;
40 import com.helger.schematron.pure.errorhandler.LoggingPSErrorHandler;
41 import com.helger.schematron.svrl.SVRLHelper;
42 import com.helger.schematron.testfiles.SchematronTestHelper;
43 import com.helger.schematron.xpath.XQueryAsXPathFunctionConverter;
44 import com.helger.xml.schema.XMLSchemaCache;
45 import com.helger.xml.serialize.read.DOMReader;
46 import com.helger.xml.serialize.read.DOMReaderSettings;
47 import com.helger.xml.xpath.MapBasedXPathFunctionResolver;
48 import com.helger.xml.xpath.MapBasedXPathVariableResolver;
49
50
51
52
53
54
55 public final class SchematronResourcePureTest
56 {
57 @Test
58 public void testBasic () throws Exception
59 {
60 for (final IReadableResource aRes : SchematronTestHelper.getAllValidSchematronFiles ())
61 {
62
63
64 final SchematronResourcePure aResPure = new SchematronResourcePure (aRes);
65 assertTrue (aRes.getPath (), aResPure.isValidSchematron ());
66 }
67 }
68
69 @Test
70 public void testFromByteArray ()
71 {
72 final String sTest = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" +
73 "<iso:schema xmlns=\"http://purl.oclc.org/dsdl/schematron\" \n" +
74 " xmlns:iso=\"http://purl.oclc.org/dsdl/schematron\" \n" +
75 " xmlns:sch=\"http://www.ascc.net/xml/schematron\"\n" +
76 " queryBinding='xslt2'\n" +
77 " schemaVersion=\"ISO19757-3\">\n" +
78 " <iso:title>Test ISO schematron file. Introduction mode</iso:title>\n" +
79 " <iso:ns prefix=\"dp\" uri=\"http://www.dpawson.co.uk/ns#\" />\n" +
80 " <iso:pattern >\n" +
81 " <iso:title>A very simple pattern with a title</iso:title>\n" +
82 " <iso:rule context=\"chapter\">\n" +
83 " <iso:assert test=\"title\">Chapter should have a title</iso:assert>\n" +
84 " <iso:report test=\"count(para)\">\n" +
85 " <iso:value-of select=\"count(para)\"/> paragraphs</iso:report>\n" +
86 " </iso:rule>\n" +
87 " </iso:pattern>\n" +
88 "\n" +
89 "</iso:schema>";
90 assertTrue (SchematronResourcePure.fromByteArray (sTest.getBytes (StandardCharsets.UTF_8)).isValidSchematron ());
91 assertTrue (SchematronResourcePure.fromInputStream (new StringInputStream (sTest, StandardCharsets.UTF_8))
92 .isValidSchematron ());
93 }
94
95 @Test
96 public void testParseWithXPathError ()
97 {
98 final String sTest = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" +
99 "<iso:schema xmlns=\"http://purl.oclc.org/dsdl/schematron\" \n" +
100 " xmlns:iso=\"http://purl.oclc.org/dsdl/schematron\" \n" +
101 " xmlns:sch=\"http://www.ascc.net/xml/schematron\"\n" +
102 " queryBinding='xslt2'\n" +
103 " schemaVersion=\"ISO19757-3\">\n" +
104 " <iso:title>Test ISO schematron file. Introduction mode</iso:title>\n" +
105 " <iso:ns prefix=\"dp\" uri=\"http://www.dpawson.co.uk/ns#\" />\n" +
106 " <iso:pattern>\n" +
107 " <iso:rule context=\"chapter\">\n"
108
109
110 +
111 " <iso:assert test=\"title xor 55\">Chapter should have a title</iso:assert>\n"
112
113
114 +
115 " <iso:assert test=\"title xor 33\">Chapter should have a title</iso:assert>\n" +
116 " </iso:rule>\n" +
117 " </iso:pattern>\n" +
118 "</iso:schema>";
119 final CollectingPSErrorHandler aErrorHandler = new CollectingPSErrorHandler ();
120 final SchematronResourcePure aSch = SchematronResourcePure.fromByteArray (sTest.getBytes (StandardCharsets.UTF_8))
121 .setErrorHandler (aErrorHandler);
122
123 assertFalse (aSch.isValidSchematron ());
124 assertEquals ("Expected three errors: " + aErrorHandler.getErrorList ().toString (),
125 3,
126 aErrorHandler.getErrorList ().size ());
127 if (false)
128 System.out.println (aErrorHandler.getErrorList ().toString ());
129
130
131 aErrorHandler.clearResourceErrors ();
132 aSch.validateCompletely ();
133 assertEquals ("Expected three errors: " + aErrorHandler.getErrorList ().toString (),
134 3,
135 aErrorHandler.getErrorList ().size ());
136 }
137
138 @Test
139 public void testResolveVariables () throws SchematronException
140 {
141 final String sTest = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" +
142 "<iso:schema xmlns=\"http://purl.oclc.org/dsdl/schematron\" \n" +
143 " xmlns:iso=\"http://purl.oclc.org/dsdl/schematron\" \n" +
144 " xmlns:sch=\"http://www.ascc.net/xml/schematron\"\n" +
145 " queryBinding='xslt2'\n" +
146 " schemaVersion=\"ISO19757-3\">\n" +
147 " <iso:title>Test ISO schematron file. Introduction mode</iso:title>\n" +
148 " <iso:ns prefix=\"dp\" uri=\"http://www.dpawson.co.uk/ns#\" />\n" +
149 " <iso:ns prefix=\"java\" uri=\"http://helger.com/schematron/test\" />\n" +
150 " <iso:pattern >\n" +
151 " <iso:title>A very simple pattern with a title</iso:title>\n" +
152 " <iso:rule context=\"chapter\">\n"
153
154 +
155 " <iso:assert test=\"$title-element\">Chapter should have a title</iso:assert>\n"
156
157 +
158 " <iso:report test=\"java:my-count(para) = 2\">\n"
159
160 +
161 " <iso:value-of select=\"java:my-count(para)\"/> paragraphs found</iso:report>\n" +
162 " </iso:rule>\n" +
163 " </iso:pattern>\n" +
164 "\n" +
165 "</iso:schema>";
166
167
168
169 assertFalse (SchematronResourcePure.fromString (sTest, StandardCharsets.UTF_8)
170 .setErrorHandler (new DoNothingPSErrorHandler ())
171 .isValidSchematron ());
172
173
174 final MapBasedXPathVariableResolver aVarResolver = new MapBasedXPathVariableResolver ();
175 aVarResolver.addUniqueVariable ("title-element", "title");
176
177 final MapBasedXPathFunctionResolver aFunctionResolver = new MapBasedXPathFunctionResolver ();
178 aFunctionResolver.addUniqueFunction ("http://helger.com/schematron/test", "my-count", 1, args -> {
179 final List <?> aArg = (List <?>) args.get (0);
180 return Integer.valueOf (aArg.size ());
181 });
182 final Document aTestDoc = DOMReader.readXMLDOM ("<?xml version='1.0'?><chapter><title /><para>First para</para><para>Second para</para></chapter>");
183 final SchematronOutputType aOT = SchematronResourcePure.fromString (sTest, StandardCharsets.UTF_8)
184 .setVariableResolver (aVarResolver)
185 .setFunctionResolver (aFunctionResolver)
186 .applySchematronValidationToSVRL (aTestDoc, null);
187 assertNotNull (aOT);
188 assertEquals (0, SVRLHelper.getAllFailedAssertions (aOT).size ());
189 assertEquals (1, SVRLHelper.getAllSuccessfulReports (aOT).size ());
190
191 assertEquals ("\n 2 paragraphs found".trim (), SVRLHelper.getAllSuccessfulReports (aOT).get (0).getText ());
192 }
193
194 @Test
195 public void testResolveFunctions () throws SchematronException
196 {
197 final String sTest = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" +
198 "<iso:schema xmlns=\"http://purl.oclc.org/dsdl/schematron\" \n" +
199 " xmlns:iso=\"http://purl.oclc.org/dsdl/schematron\" \n" +
200 " xmlns:sch=\"http://www.ascc.net/xml/schematron\"\n" +
201 " queryBinding='xslt2'\n" +
202 " schemaVersion=\"ISO19757-3\">\n" +
203 " <iso:title>Test ISO schematron file. Introduction mode</iso:title>\n" +
204 " <iso:ns prefix=\"dp\" uri=\"http://www.dpawson.co.uk/ns#\" />\n" +
205 " <iso:ns prefix=\"java\" uri=\"http://helger.com/schematron/test\" />\n" +
206 " <iso:pattern >\n" +
207 " <iso:title>A very simple pattern with a title</iso:title>\n" +
208 " <iso:rule context=\"chapter\">\n" +
209 " <iso:assert test=\"title\">Chapter should have a title</iso:assert>\n" +
210 " <iso:report test=\"count(para) = 2\">\n"
211
212 +
213 " Node details: <iso:value-of select=\"java:get-nodelist-details(para)\"/> - end</iso:report>\n" +
214 " </iso:rule>\n" +
215 " </iso:pattern>\n" +
216 "\n" +
217 "</iso:schema>";
218
219
220 final MapBasedXPathFunctionResolver aFunctionResolver = new MapBasedXPathFunctionResolver ();
221 aFunctionResolver.addUniqueFunction ("http://helger.com/schematron/test", "get-nodelist-details", 1, args -> {
222
223 assertEquals (1, args.size ());
224
225
226 final List <?> aFirstArg = (List <?>) args.get (0);
227
228
229 final StringBuilder ret = new StringBuilder ();
230 boolean bFirst = true;
231 for (final Object aFirstArgItem : aFirstArg)
232 {
233 assertTrue (aFirstArgItem instanceof Node);
234 final Node aNode = (Node) aFirstArgItem;
235
236 if (bFirst)
237 bFirst = false;
238 else
239 ret.append (", ");
240
241 ret.append (aNode.getNodeName ()).append ("[").append (aNode.getTextContent ()).append ("]");
242 }
243
244 return ret;
245 });
246
247 final Document aTestDoc = DOMReader.readXMLDOM ("<?xml version='1.0'?>" +
248 "<chapter>" +
249 "<title />" +
250 "<para>First para</para>" +
251 "<para>Second para</para>" +
252 "</chapter>");
253 final SchematronOutputType aOT = SchematronResourcePure.fromString (sTest, StandardCharsets.UTF_8)
254 .setFunctionResolver (aFunctionResolver)
255 .applySchematronValidationToSVRL (aTestDoc, null);
256 assertNotNull (aOT);
257 assertEquals (0, SVRLHelper.getAllFailedAssertions (aOT).size ());
258 assertEquals (1, SVRLHelper.getAllSuccessfulReports (aOT).size ());
259
260 assertEquals ("\n Node details: para[First para], para[Second para] - end".trim (),
261 SVRLHelper.getAllSuccessfulReports (aOT).get (0).getText ());
262 }
263
264 @Test
265 public void testResolveXQueryFunctions () throws Exception
266 {
267 final String sTest = "<?xml version='1.0' encoding='iso-8859-1'?>\n" +
268 "<iso:schema xmlns='http://purl.oclc.org/dsdl/schematron' \n" +
269 " xmlns:iso='http://purl.oclc.org/dsdl/schematron' \n" +
270 " xmlns:sch='http://www.ascc.net/xml/schematron'\n" +
271 " queryBinding='xslt2'\n" +
272 " schemaVersion='ISO19757-3'>\n" +
273 " <iso:title>Test ISO schematron file. Introduction mode</iso:title>\n" +
274 " <iso:ns prefix='dp' uri='http://www.dpawson.co.uk/ns#' />\n" +
275 " <iso:ns prefix='functx' uri='http://www.functx.com' />\n" +
276 " <iso:pattern >\n" +
277 " <iso:title>A very simple pattern with a title</iso:title>\n" +
278 " <iso:rule context='chapter'>\n" +
279 " <iso:assert test='title'>Chapter should have a title</iso:assert>\n" +
280 " <iso:report test='count(para) = 2'>\n"
281
282 +
283 " Node kind: <iso:value-of select='functx:node-kind(para)'/> - end</iso:report>\n" +
284 " </iso:rule>\n" +
285 " </iso:pattern>\n" +
286 "\n" +
287 "</iso:schema>";
288
289 final MapBasedXPathFunctionResolver aFunctionResolver = new XQueryAsXPathFunctionConverter ().loadXQuery (ClassPathResource.getInputStream ("xquery/functx-1.0-nodoc-2007-01.xq"));
290
291
292 final Document aTestDoc = DOMReader.readXMLDOM ("<?xml version='1.0'?>" +
293 "<chapter>" +
294 "<title />" +
295 "<para>First para</para>" +
296 "<para>Second para</para>" +
297 "</chapter>");
298 final SchematronOutputType aOT = SchematronResourcePure.fromString (sTest, StandardCharsets.UTF_8)
299 .setFunctionResolver (aFunctionResolver)
300 .applySchematronValidationToSVRL (aTestDoc, null);
301 assertNotNull (aOT);
302 assertEquals (0, SVRLHelper.getAllFailedAssertions (aOT).size ());
303 assertEquals (1, SVRLHelper.getAllSuccessfulReports (aOT).size ());
304
305 assertEquals ("\n Node kind: element - end".trim (),
306 SVRLHelper.getAllSuccessfulReports (aOT).get (0).getText ());
307 }
308
309 @Test
310 public void testResolveFunctXAreDistinctValuesQueryFunctions () throws Exception
311 {
312 final String sTest = "<?xml version='1.0' encoding='iso-8859-1'?>\n" +
313 "<iso:schema xmlns='http://purl.oclc.org/dsdl/schematron' \n" +
314 " xmlns:iso='http://purl.oclc.org/dsdl/schematron' \n" +
315 " xmlns:sch='http://www.ascc.net/xml/schematron'\n" +
316 " queryBinding='xslt2'\n" +
317 " schemaVersion='ISO19757-3'>\n" +
318 " <iso:title>Test ISO schematron file. Introduction mode</iso:title>\n" +
319 " <iso:ns prefix='dp' uri='http://www.dpawson.co.uk/ns#' />\n" +
320 " <iso:ns prefix='fn' uri='http://www.w3.org/2005/xpath-functions' />\n" +
321 " <iso:ns prefix='functx' uri='http://www.functx.com' />\n" +
322 " <iso:pattern >\n" +
323 " <iso:title>A very simple pattern with a title</iso:title>\n" +
324 " <iso:rule context='chapter'>\n" +
325 " <iso:assert test='functx:are-distinct-values(para)'>Should have distinct values</iso:assert>\n" +
326 " </iso:rule>\n" +
327 " </iso:pattern>\n" +
328 "</iso:schema>";
329
330 final MapBasedXPathFunctionResolver aFunctionResolver = new XQueryAsXPathFunctionConverter ().loadXQuery (ClassPathResource.getInputStream ("xquery/functx-1.0-nodoc-2007-01.xq"));
331
332
333 final Document aTestDoc = DOMReader.readXMLDOM ("<?xml version='1.0'?>" +
334 "<chapter>" +
335 "<title />" +
336 "<para>100</para>" +
337 "<para>200</para>" +
338 "</chapter>");
339 final CollectingPSErrorHandler aErrorHandler = new CollectingPSErrorHandler (new LoggingPSErrorHandler ());
340 final SchematronOutputType aOT = SchematronResourcePure.fromString (sTest, StandardCharsets.UTF_8)
341 .setFunctionResolver (aFunctionResolver)
342 .setErrorHandler (aErrorHandler)
343 .applySchematronValidationToSVRL (aTestDoc, null);
344 assertNotNull (aOT);
345
346 if (false)
347 assertTrue (aErrorHandler.getAllErrors ().toString (), aErrorHandler.isEmpty ());
348 assertEquals (0, SVRLHelper.getAllFailedAssertions (aOT).size ());
349 }
350
351 @Test
352 public void testFunctXAreDistinctValuesWithXSD () throws Exception
353 {
354 final String sTest = "<?xml version='1.0' encoding='iso-8859-1'?>\n" +
355 "<schema xmlns='http://purl.oclc.org/dsdl/schematron'>\n" +
356 " <ns prefix=\"xs\" uri=\"http://www.w3.org/2001/XMLSchema\"/>\n" +
357 " <ns prefix='fn' uri='http://www.w3.org/2005/xpath-functions' />\n" +
358 " <ns prefix='functx' uri='http://www.functx.com' />\n" +
359 " <pattern name='toto'>\n" +
360 " <title>A very simple pattern with a title</title>\n" +
361 " <rule context='chapter'>\n" +
362 " <assert test='fn:count(fn:distinct-values(para)) = fn:count(para)'>Should have distinct values</assert>\n" +
363 " </rule>\n" +
364 " </pattern>\n" +
365 "</schema>";
366
367 final MapBasedXPathFunctionResolver aFunctionResolver = new XQueryAsXPathFunctionConverter ().loadXQuery (ClassPathResource.getInputStream ("xquery/functx-1.0-nodoc-2007-01.xq"));
368
369 final Schema aSchema = XMLSchemaCache.getInstance ()
370 .getSchema (new ClassPathResource ("issues/20141124/chapter.xsd"));
371 final Document aTestDoc = DOMReader.readXMLDOM ("<?xml version='1.0'?>" +
372 "<chapter>" +
373 " <title />" +
374 " <para>09</para>" +
375 " <para>9</para>" +
376 "</chapter>",
377 new DOMReaderSettings ().setSchema (aSchema));
378
379 final SchematronOutputType aOT = SchematronResourcePure.fromString (sTest, StandardCharsets.UTF_8)
380 .setFunctionResolver (aFunctionResolver)
381 .applySchematronValidationToSVRL (aTestDoc, null);
382 assertNotNull (aOT);
383 if (SVRLHelper.getAllFailedAssertions (aOT).size () != 0)
384 {
385 System.out.println (SVRLHelper.getAllFailedAssertions (aOT).get (0).getText ());
386 }
387 assertTrue (SVRLHelper.getAllFailedAssertions (aOT).isEmpty ());
388 }
389 }