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