pocxxeci 0.30.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pocxxeci might be problematic. Click here for more details.

Files changed (160) hide show
  1. package/LICENSE +19 -0
  2. package/Makefile +18 -0
  3. package/README.md +52 -0
  4. package/binding.gyp +81 -0
  5. package/index.d.ts +273 -0
  6. package/index.js +45 -0
  7. package/lib/bindings.js +1 -0
  8. package/lib/document.js +122 -0
  9. package/lib/element.js +82 -0
  10. package/lib/sax_parser.js +38 -0
  11. package/package.json +70 -0
  12. package/src/html_document.cc +7 -0
  13. package/src/html_document.h +18 -0
  14. package/src/libxmljs.cc +252 -0
  15. package/src/libxmljs.h +53 -0
  16. package/src/xml_attribute.cc +173 -0
  17. package/src/xml_attribute.h +40 -0
  18. package/src/xml_comment.cc +117 -0
  19. package/src/xml_comment.h +30 -0
  20. package/src/xml_document.cc +810 -0
  21. package/src/xml_document.h +67 -0
  22. package/src/xml_element.cc +565 -0
  23. package/src/xml_element.h +61 -0
  24. package/src/xml_namespace.cc +158 -0
  25. package/src/xml_namespace.h +39 -0
  26. package/src/xml_node.cc +761 -0
  27. package/src/xml_node.h +73 -0
  28. package/src/xml_pi.cc +161 -0
  29. package/src/xml_pi.h +34 -0
  30. package/src/xml_sax_parser.cc +424 -0
  31. package/src/xml_sax_parser.h +73 -0
  32. package/src/xml_syntax_error.cc +66 -0
  33. package/src/xml_syntax_error.h +25 -0
  34. package/src/xml_text.cc +320 -0
  35. package/src/xml_text.h +48 -0
  36. package/src/xml_textwriter.cc +315 -0
  37. package/src/xml_textwriter.h +62 -0
  38. package/src/xml_xpath_context.cc +70 -0
  39. package/src/xml_xpath_context.h +23 -0
  40. package/vendor/libxml/Copyright +23 -0
  41. package/vendor/libxml/DOCBparser.c +305 -0
  42. package/vendor/libxml/HTMLparser.c +7287 -0
  43. package/vendor/libxml/HTMLtree.c +1200 -0
  44. package/vendor/libxml/Makefile +2983 -0
  45. package/vendor/libxml/SAX.c +180 -0
  46. package/vendor/libxml/SAX2.c +3036 -0
  47. package/vendor/libxml/buf.c +1351 -0
  48. package/vendor/libxml/buf.h +72 -0
  49. package/vendor/libxml/c14n.c +2234 -0
  50. package/vendor/libxml/catalog.c +3828 -0
  51. package/vendor/libxml/chvalid.c +336 -0
  52. package/vendor/libxml/config.h +294 -0
  53. package/vendor/libxml/config.h.gch +0 -0
  54. package/vendor/libxml/debugXML.c +3423 -0
  55. package/vendor/libxml/dict.c +1298 -0
  56. package/vendor/libxml/elfgcchack.h +17818 -0
  57. package/vendor/libxml/enc.h +32 -0
  58. package/vendor/libxml/encoding.c +3975 -0
  59. package/vendor/libxml/entities.c +1163 -0
  60. package/vendor/libxml/error.c +998 -0
  61. package/vendor/libxml/globals.c +1126 -0
  62. package/vendor/libxml/hash.c +1146 -0
  63. package/vendor/libxml/include/libxml/DOCBparser.h +96 -0
  64. package/vendor/libxml/include/libxml/HTMLparser.h +306 -0
  65. package/vendor/libxml/include/libxml/HTMLtree.h +147 -0
  66. package/vendor/libxml/include/libxml/Makefile +725 -0
  67. package/vendor/libxml/include/libxml/Makefile.am +54 -0
  68. package/vendor/libxml/include/libxml/Makefile.in +725 -0
  69. package/vendor/libxml/include/libxml/SAX.h +173 -0
  70. package/vendor/libxml/include/libxml/SAX2.h +178 -0
  71. package/vendor/libxml/include/libxml/c14n.h +128 -0
  72. package/vendor/libxml/include/libxml/catalog.h +182 -0
  73. package/vendor/libxml/include/libxml/chvalid.h +230 -0
  74. package/vendor/libxml/include/libxml/debugXML.h +217 -0
  75. package/vendor/libxml/include/libxml/dict.h +79 -0
  76. package/vendor/libxml/include/libxml/encoding.h +245 -0
  77. package/vendor/libxml/include/libxml/entities.h +151 -0
  78. package/vendor/libxml/include/libxml/globals.h +508 -0
  79. package/vendor/libxml/include/libxml/hash.h +236 -0
  80. package/vendor/libxml/include/libxml/list.h +137 -0
  81. package/vendor/libxml/include/libxml/nanoftp.h +163 -0
  82. package/vendor/libxml/include/libxml/nanohttp.h +81 -0
  83. package/vendor/libxml/include/libxml/parser.h +1243 -0
  84. package/vendor/libxml/include/libxml/parserInternals.h +644 -0
  85. package/vendor/libxml/include/libxml/pattern.h +100 -0
  86. package/vendor/libxml/include/libxml/relaxng.h +217 -0
  87. package/vendor/libxml/include/libxml/schemasInternals.h +958 -0
  88. package/vendor/libxml/include/libxml/schematron.h +142 -0
  89. package/vendor/libxml/include/libxml/threads.h +89 -0
  90. package/vendor/libxml/include/libxml/tree.h +1311 -0
  91. package/vendor/libxml/include/libxml/uri.h +94 -0
  92. package/vendor/libxml/include/libxml/valid.h +458 -0
  93. package/vendor/libxml/include/libxml/xinclude.h +129 -0
  94. package/vendor/libxml/include/libxml/xlink.h +189 -0
  95. package/vendor/libxml/include/libxml/xmlIO.h +368 -0
  96. package/vendor/libxml/include/libxml/xmlautomata.h +146 -0
  97. package/vendor/libxml/include/libxml/xmlerror.h +945 -0
  98. package/vendor/libxml/include/libxml/xmlexports.h +77 -0
  99. package/vendor/libxml/include/libxml/xmlmemory.h +224 -0
  100. package/vendor/libxml/include/libxml/xmlmodule.h +57 -0
  101. package/vendor/libxml/include/libxml/xmlreader.h +428 -0
  102. package/vendor/libxml/include/libxml/xmlregexp.h +222 -0
  103. package/vendor/libxml/include/libxml/xmlsave.h +88 -0
  104. package/vendor/libxml/include/libxml/xmlschemas.h +246 -0
  105. package/vendor/libxml/include/libxml/xmlschemastypes.h +151 -0
  106. package/vendor/libxml/include/libxml/xmlstring.h +140 -0
  107. package/vendor/libxml/include/libxml/xmlunicode.h +202 -0
  108. package/vendor/libxml/include/libxml/xmlversion.h +484 -0
  109. package/vendor/libxml/include/libxml/xmlwin32version.h +239 -0
  110. package/vendor/libxml/include/libxml/xmlwriter.h +488 -0
  111. package/vendor/libxml/include/libxml/xpath.h +564 -0
  112. package/vendor/libxml/include/libxml/xpathInternals.h +632 -0
  113. package/vendor/libxml/include/libxml/xpointer.h +114 -0
  114. package/vendor/libxml/include/win32config.h +122 -0
  115. package/vendor/libxml/include/wsockcompat.h +54 -0
  116. package/vendor/libxml/legacy.c +1343 -0
  117. package/vendor/libxml/libxml.h +134 -0
  118. package/vendor/libxml/list.c +779 -0
  119. package/vendor/libxml/nanoftp.c +2118 -0
  120. package/vendor/libxml/nanohttp.c +1899 -0
  121. package/vendor/libxml/parser.c +15553 -0
  122. package/vendor/libxml/parserInternals.c +2164 -0
  123. package/vendor/libxml/pattern.c +2621 -0
  124. package/vendor/libxml/relaxng.c +11101 -0
  125. package/vendor/libxml/rngparser.c +1595 -0
  126. package/vendor/libxml/runsuite.c +1157 -0
  127. package/vendor/libxml/save.h +36 -0
  128. package/vendor/libxml/schematron.c +1787 -0
  129. package/vendor/libxml/threads.c +1049 -0
  130. package/vendor/libxml/timsort.h +601 -0
  131. package/vendor/libxml/tree.c +10183 -0
  132. package/vendor/libxml/trio.c +6895 -0
  133. package/vendor/libxml/trio.h +230 -0
  134. package/vendor/libxml/triodef.h +228 -0
  135. package/vendor/libxml/trionan.c +914 -0
  136. package/vendor/libxml/trionan.h +84 -0
  137. package/vendor/libxml/triop.h +150 -0
  138. package/vendor/libxml/triostr.c +2112 -0
  139. package/vendor/libxml/triostr.h +144 -0
  140. package/vendor/libxml/uri.c +2561 -0
  141. package/vendor/libxml/valid.c +7138 -0
  142. package/vendor/libxml/xinclude.c +2657 -0
  143. package/vendor/libxml/xlink.c +183 -0
  144. package/vendor/libxml/xmlIO.c +4135 -0
  145. package/vendor/libxml/xmlcatalog.c +624 -0
  146. package/vendor/libxml/xmllint.c +3796 -0
  147. package/vendor/libxml/xmlmemory.c +1163 -0
  148. package/vendor/libxml/xmlmodule.c +468 -0
  149. package/vendor/libxml/xmlreader.c +6033 -0
  150. package/vendor/libxml/xmlregexp.c +8271 -0
  151. package/vendor/libxml/xmlsave.c +2735 -0
  152. package/vendor/libxml/xmlschemas.c +29173 -0
  153. package/vendor/libxml/xmlschemastypes.c +6276 -0
  154. package/vendor/libxml/xmlstring.c +1050 -0
  155. package/vendor/libxml/xmlunicode.c +3179 -0
  156. package/vendor/libxml/xmlwriter.c +4738 -0
  157. package/vendor/libxml/xpath.c +14734 -0
  158. package/vendor/libxml/xpointer.c +2969 -0
  159. package/vendor/libxml/xzlib.c +815 -0
  160. package/vendor/libxml/xzlib.h +19 -0
@@ -0,0 +1,1787 @@
1
+ /*
2
+ * schematron.c : implementation of the Schematron schema validity checking
3
+ *
4
+ * See Copyright for the status of this software.
5
+ *
6
+ * Daniel Veillard <daniel@veillard.com>
7
+ */
8
+
9
+ /*
10
+ * TODO:
11
+ * + double check the semantic, especially
12
+ * - multiple rules applying in a single pattern/node
13
+ * - the semantic of libxml2 patterns vs. XSLT production referenced
14
+ * by the spec.
15
+ * + export of results in SVRL
16
+ * + full parsing and coverage of the spec, conformance of the input to the
17
+ * spec
18
+ * + divergences between the draft and the ISO proposed standard :-(
19
+ * + hook and test include
20
+ * + try and compare with the XSLT version
21
+ */
22
+
23
+ #define IN_LIBXML
24
+ #include "libxml.h"
25
+
26
+ #ifdef LIBXML_SCHEMATRON_ENABLED
27
+
28
+ #include <string.h>
29
+ #include <libxml/parser.h>
30
+ #include <libxml/tree.h>
31
+ #include <libxml/uri.h>
32
+ #include <libxml/xpath.h>
33
+ #include <libxml/xpathInternals.h>
34
+ #include <libxml/pattern.h>
35
+ #include <libxml/schematron.h>
36
+
37
+ #define SCHEMATRON_PARSE_OPTIONS XML_PARSE_NOENT
38
+
39
+ #define SCT_OLD_NS BAD_CAST "http://www.ascc.net/xml/schematron"
40
+
41
+ #define XML_SCHEMATRON_NS BAD_CAST "http://purl.oclc.org/dsdl/schematron"
42
+
43
+
44
+ static const xmlChar *xmlSchematronNs = XML_SCHEMATRON_NS;
45
+ static const xmlChar *xmlOldSchematronNs = SCT_OLD_NS;
46
+
47
+ #define IS_SCHEMATRON(node, elem) \
48
+ ((node != NULL) && (node->type == XML_ELEMENT_NODE ) && \
49
+ (node->ns != NULL) && \
50
+ (xmlStrEqual(node->name, (const xmlChar *) elem)) && \
51
+ ((xmlStrEqual(node->ns->href, xmlSchematronNs)) || \
52
+ (xmlStrEqual(node->ns->href, xmlOldSchematronNs))))
53
+
54
+ #define NEXT_SCHEMATRON(node) \
55
+ while (node != NULL) { \
56
+ if ((node->type == XML_ELEMENT_NODE ) && (node->ns != NULL) && \
57
+ ((xmlStrEqual(node->ns->href, xmlSchematronNs)) || \
58
+ (xmlStrEqual(node->ns->href, xmlOldSchematronNs)))) \
59
+ break; \
60
+ node = node->next; \
61
+ }
62
+
63
+ /**
64
+ * TODO:
65
+ *
66
+ * macro to flag unimplemented blocks
67
+ */
68
+ #define TODO \
69
+ xmlGenericError(xmlGenericErrorContext, \
70
+ "Unimplemented block at %s:%d\n", \
71
+ __FILE__, __LINE__);
72
+
73
+ typedef enum {
74
+ XML_SCHEMATRON_ASSERT=1,
75
+ XML_SCHEMATRON_REPORT=2
76
+ } xmlSchematronTestType;
77
+
78
+ /**
79
+ * _xmlSchematronTest:
80
+ *
81
+ * A Schematrons test, either an assert or a report
82
+ */
83
+ typedef struct _xmlSchematronTest xmlSchematronTest;
84
+ typedef xmlSchematronTest *xmlSchematronTestPtr;
85
+ struct _xmlSchematronTest {
86
+ xmlSchematronTestPtr next; /* the next test in the list */
87
+ xmlSchematronTestType type; /* the test type */
88
+ xmlNodePtr node; /* the node in the tree */
89
+ xmlChar *test; /* the expression to test */
90
+ xmlXPathCompExprPtr comp; /* the compiled expression */
91
+ xmlChar *report; /* the message to report */
92
+ };
93
+
94
+ /**
95
+ * _xmlSchematronRule:
96
+ *
97
+ * A Schematrons rule
98
+ */
99
+ typedef struct _xmlSchematronRule xmlSchematronRule;
100
+ typedef xmlSchematronRule *xmlSchematronRulePtr;
101
+ struct _xmlSchematronRule {
102
+ xmlSchematronRulePtr next; /* the next rule in the list */
103
+ xmlSchematronRulePtr patnext;/* the next rule in the pattern list */
104
+ xmlNodePtr node; /* the node in the tree */
105
+ xmlChar *context; /* the context evaluation rule */
106
+ xmlSchematronTestPtr tests; /* the list of tests */
107
+ xmlPatternPtr pattern; /* the compiled pattern associated */
108
+ xmlChar *report; /* the message to report */
109
+ };
110
+
111
+ /**
112
+ * _xmlSchematronPattern:
113
+ *
114
+ * A Schematrons pattern
115
+ */
116
+ typedef struct _xmlSchematronPattern xmlSchematronPattern;
117
+ typedef xmlSchematronPattern *xmlSchematronPatternPtr;
118
+ struct _xmlSchematronPattern {
119
+ xmlSchematronPatternPtr next;/* the next pattern in the list */
120
+ xmlSchematronRulePtr rules; /* the list of rules */
121
+ xmlChar *name; /* the name of the pattern */
122
+ };
123
+
124
+ /**
125
+ * _xmlSchematron:
126
+ *
127
+ * A Schematrons definition
128
+ */
129
+ struct _xmlSchematron {
130
+ const xmlChar *name; /* schema name */
131
+ int preserve; /* was the document passed by the user */
132
+ xmlDocPtr doc; /* pointer to the parsed document */
133
+ int flags; /* specific to this schematron */
134
+
135
+ void *_private; /* unused by the library */
136
+ xmlDictPtr dict; /* the dictionary used internally */
137
+
138
+ const xmlChar *title; /* the title if any */
139
+
140
+ int nbNs; /* the number of namespaces */
141
+
142
+ int nbPattern; /* the number of patterns */
143
+ xmlSchematronPatternPtr patterns;/* the patterns found */
144
+ xmlSchematronRulePtr rules; /* the rules gathered */
145
+ int nbNamespaces; /* number of namespaces in the array */
146
+ int maxNamespaces; /* size of the array */
147
+ const xmlChar **namespaces; /* the array of namespaces */
148
+ };
149
+
150
+ /**
151
+ * xmlSchematronValidCtxt:
152
+ *
153
+ * A Schematrons validation context
154
+ */
155
+ struct _xmlSchematronValidCtxt {
156
+ int type;
157
+ int flags; /* an or of xmlSchematronValidOptions */
158
+
159
+ xmlDictPtr dict;
160
+ int nberrors;
161
+ int err;
162
+
163
+ xmlSchematronPtr schema;
164
+ xmlXPathContextPtr xctxt;
165
+
166
+ FILE *outputFile; /* if using XML_SCHEMATRON_OUT_FILE */
167
+ xmlBufferPtr outputBuffer; /* if using XML_SCHEMATRON_OUT_BUFFER */
168
+ #ifdef LIBXML_OUTPUT_ENABLED
169
+ xmlOutputWriteCallback iowrite; /* if using XML_SCHEMATRON_OUT_IO */
170
+ xmlOutputCloseCallback ioclose;
171
+ #endif
172
+ void *ioctx;
173
+
174
+ /* error reporting data */
175
+ void *userData; /* user specific data block */
176
+ xmlSchematronValidityErrorFunc error;/* the callback in case of errors */
177
+ xmlSchematronValidityWarningFunc warning;/* callback in case of warning */
178
+ xmlStructuredErrorFunc serror; /* the structured function */
179
+ };
180
+
181
+ struct _xmlSchematronParserCtxt {
182
+ int type;
183
+ const xmlChar *URL;
184
+ xmlDocPtr doc;
185
+ int preserve; /* Whether the doc should be freed */
186
+ const char *buffer;
187
+ int size;
188
+
189
+ xmlDictPtr dict; /* dictionary for interned string names */
190
+
191
+ int nberrors;
192
+ int err;
193
+ xmlXPathContextPtr xctxt; /* the XPath context used for compilation */
194
+ xmlSchematronPtr schema;
195
+
196
+ int nbNamespaces; /* number of namespaces in the array */
197
+ int maxNamespaces; /* size of the array */
198
+ const xmlChar **namespaces; /* the array of namespaces */
199
+
200
+ int nbIncludes; /* number of includes in the array */
201
+ int maxIncludes; /* size of the array */
202
+ xmlNodePtr *includes; /* the array of includes */
203
+
204
+ /* error reporting data */
205
+ void *userData; /* user specific data block */
206
+ xmlSchematronValidityErrorFunc error;/* the callback in case of errors */
207
+ xmlSchematronValidityWarningFunc warning;/* callback in case of warning */
208
+ xmlStructuredErrorFunc serror; /* the structured function */
209
+ };
210
+
211
+ #define XML_STRON_CTXT_PARSER 1
212
+ #define XML_STRON_CTXT_VALIDATOR 2
213
+
214
+ /************************************************************************
215
+ * *
216
+ * Error reporting *
217
+ * *
218
+ ************************************************************************/
219
+
220
+ /**
221
+ * xmlSchematronPErrMemory:
222
+ * @node: a context node
223
+ * @extra: extra information
224
+ *
225
+ * Handle an out of memory condition
226
+ */
227
+ static void
228
+ xmlSchematronPErrMemory(xmlSchematronParserCtxtPtr ctxt,
229
+ const char *extra, xmlNodePtr node)
230
+ {
231
+ if (ctxt != NULL)
232
+ ctxt->nberrors++;
233
+ __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
234
+ extra);
235
+ }
236
+
237
+ /**
238
+ * xmlSchematronPErr:
239
+ * @ctxt: the parsing context
240
+ * @node: the context node
241
+ * @error: the error code
242
+ * @msg: the error message
243
+ * @str1: extra data
244
+ * @str2: extra data
245
+ *
246
+ * Handle a parser error
247
+ */
248
+ static void LIBXML_ATTR_FORMAT(4,0)
249
+ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error,
250
+ const char *msg, const xmlChar * str1, const xmlChar * str2)
251
+ {
252
+ xmlGenericErrorFunc channel = NULL;
253
+ xmlStructuredErrorFunc schannel = NULL;
254
+ void *data = NULL;
255
+
256
+ if (ctxt != NULL) {
257
+ ctxt->nberrors++;
258
+ channel = ctxt->error;
259
+ data = ctxt->userData;
260
+ schannel = ctxt->serror;
261
+ }
262
+ __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
263
+ error, XML_ERR_ERROR, NULL, 0,
264
+ (const char *) str1, (const char *) str2, NULL, 0, 0,
265
+ msg, str1, str2);
266
+ }
267
+
268
+ /**
269
+ * xmlSchematronVTypeErrMemory:
270
+ * @node: a context node
271
+ * @extra: extra information
272
+ *
273
+ * Handle an out of memory condition
274
+ */
275
+ static void
276
+ xmlSchematronVErrMemory(xmlSchematronValidCtxtPtr ctxt,
277
+ const char *extra, xmlNodePtr node)
278
+ {
279
+ if (ctxt != NULL) {
280
+ ctxt->nberrors++;
281
+ ctxt->err = XML_SCHEMAV_INTERNAL;
282
+ }
283
+ __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
284
+ extra);
285
+ }
286
+
287
+ /************************************************************************
288
+ * *
289
+ * Parsing and compilation of the Schematrontrons *
290
+ * *
291
+ ************************************************************************/
292
+
293
+ /**
294
+ * xmlSchematronAddTest:
295
+ * @ctxt: the schema parsing context
296
+ * @type: the type of test
297
+ * @rule: the parent rule
298
+ * @node: the node hosting the test
299
+ * @test: the associated test
300
+ * @report: the associated report string
301
+ *
302
+ * Add a test to a schematron
303
+ *
304
+ * Returns the new pointer or NULL in case of error
305
+ */
306
+ static xmlSchematronTestPtr
307
+ xmlSchematronAddTest(xmlSchematronParserCtxtPtr ctxt,
308
+ xmlSchematronTestType type,
309
+ xmlSchematronRulePtr rule,
310
+ xmlNodePtr node, xmlChar *test, xmlChar *report)
311
+ {
312
+ xmlSchematronTestPtr ret;
313
+ xmlXPathCompExprPtr comp;
314
+
315
+ if ((ctxt == NULL) || (rule == NULL) || (node == NULL) ||
316
+ (test == NULL))
317
+ return(NULL);
318
+
319
+ /*
320
+ * try first to compile the test expression
321
+ */
322
+ comp = xmlXPathCtxtCompile(ctxt->xctxt, test);
323
+ if (comp == NULL) {
324
+ xmlSchematronPErr(ctxt, node,
325
+ XML_SCHEMAP_NOROOT,
326
+ "Failed to compile test expression %s",
327
+ test, NULL);
328
+ return(NULL);
329
+ }
330
+
331
+ ret = (xmlSchematronTestPtr) xmlMalloc(sizeof(xmlSchematronTest));
332
+ if (ret == NULL) {
333
+ xmlSchematronPErrMemory(ctxt, "allocating schema test", node);
334
+ return (NULL);
335
+ }
336
+ memset(ret, 0, sizeof(xmlSchematronTest));
337
+ ret->type = type;
338
+ ret->node = node;
339
+ ret->test = test;
340
+ ret->comp = comp;
341
+ ret->report = report;
342
+ ret->next = NULL;
343
+ if (rule->tests == NULL) {
344
+ rule->tests = ret;
345
+ } else {
346
+ xmlSchematronTestPtr prev = rule->tests;
347
+
348
+ while (prev->next != NULL)
349
+ prev = prev->next;
350
+ prev->next = ret;
351
+ }
352
+ return (ret);
353
+ }
354
+
355
+ /**
356
+ * xmlSchematronFreeTests:
357
+ * @tests: a list of tests
358
+ *
359
+ * Free a list of tests.
360
+ */
361
+ static void
362
+ xmlSchematronFreeTests(xmlSchematronTestPtr tests) {
363
+ xmlSchematronTestPtr next;
364
+
365
+ while (tests != NULL) {
366
+ next = tests->next;
367
+ if (tests->test != NULL)
368
+ xmlFree(tests->test);
369
+ if (tests->comp != NULL)
370
+ xmlXPathFreeCompExpr(tests->comp);
371
+ if (tests->report != NULL)
372
+ xmlFree(tests->report);
373
+ xmlFree(tests);
374
+ tests = next;
375
+ }
376
+ }
377
+
378
+ /**
379
+ * xmlSchematronAddRule:
380
+ * @ctxt: the schema parsing context
381
+ * @schema: a schema structure
382
+ * @node: the node hosting the rule
383
+ * @context: the associated context string
384
+ * @report: the associated report string
385
+ *
386
+ * Add a rule to a schematron
387
+ *
388
+ * Returns the new pointer or NULL in case of error
389
+ */
390
+ static xmlSchematronRulePtr
391
+ xmlSchematronAddRule(xmlSchematronParserCtxtPtr ctxt, xmlSchematronPtr schema,
392
+ xmlSchematronPatternPtr pat, xmlNodePtr node,
393
+ xmlChar *context, xmlChar *report)
394
+ {
395
+ xmlSchematronRulePtr ret;
396
+ xmlPatternPtr pattern;
397
+
398
+ if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
399
+ (context == NULL))
400
+ return(NULL);
401
+
402
+ /*
403
+ * Try first to compile the pattern
404
+ */
405
+ pattern = xmlPatterncompile(context, ctxt->dict, XML_PATTERN_XPATH,
406
+ ctxt->namespaces);
407
+ if (pattern == NULL) {
408
+ xmlSchematronPErr(ctxt, node,
409
+ XML_SCHEMAP_NOROOT,
410
+ "Failed to compile context expression %s",
411
+ context, NULL);
412
+ }
413
+
414
+ ret = (xmlSchematronRulePtr) xmlMalloc(sizeof(xmlSchematronRule));
415
+ if (ret == NULL) {
416
+ xmlSchematronPErrMemory(ctxt, "allocating schema rule", node);
417
+ return (NULL);
418
+ }
419
+ memset(ret, 0, sizeof(xmlSchematronRule));
420
+ ret->node = node;
421
+ ret->context = context;
422
+ ret->pattern = pattern;
423
+ ret->report = report;
424
+ ret->next = NULL;
425
+ if (schema->rules == NULL) {
426
+ schema->rules = ret;
427
+ } else {
428
+ xmlSchematronRulePtr prev = schema->rules;
429
+
430
+ while (prev->next != NULL)
431
+ prev = prev->next;
432
+ prev->next = ret;
433
+ }
434
+ ret->patnext = NULL;
435
+ if (pat->rules == NULL) {
436
+ pat->rules = ret;
437
+ } else {
438
+ xmlSchematronRulePtr prev = pat->rules;
439
+
440
+ while (prev->patnext != NULL)
441
+ prev = prev->patnext;
442
+ prev->patnext = ret;
443
+ }
444
+ return (ret);
445
+ }
446
+
447
+ /**
448
+ * xmlSchematronFreeRules:
449
+ * @rules: a list of rules
450
+ *
451
+ * Free a list of rules.
452
+ */
453
+ static void
454
+ xmlSchematronFreeRules(xmlSchematronRulePtr rules) {
455
+ xmlSchematronRulePtr next;
456
+
457
+ while (rules != NULL) {
458
+ next = rules->next;
459
+ if (rules->tests)
460
+ xmlSchematronFreeTests(rules->tests);
461
+ if (rules->context != NULL)
462
+ xmlFree(rules->context);
463
+ if (rules->pattern)
464
+ xmlFreePattern(rules->pattern);
465
+ if (rules->report != NULL)
466
+ xmlFree(rules->report);
467
+ xmlFree(rules);
468
+ rules = next;
469
+ }
470
+ }
471
+
472
+ /**
473
+ * xmlSchematronAddPattern:
474
+ * @ctxt: the schema parsing context
475
+ * @schema: a schema structure
476
+ * @node: the node hosting the pattern
477
+ * @id: the id or name of the pattern
478
+ *
479
+ * Add a pattern to a schematron
480
+ *
481
+ * Returns the new pointer or NULL in case of error
482
+ */
483
+ static xmlSchematronPatternPtr
484
+ xmlSchematronAddPattern(xmlSchematronParserCtxtPtr ctxt,
485
+ xmlSchematronPtr schema, xmlNodePtr node, xmlChar *name)
486
+ {
487
+ xmlSchematronPatternPtr ret;
488
+
489
+ if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || (name == NULL))
490
+ return(NULL);
491
+
492
+ ret = (xmlSchematronPatternPtr) xmlMalloc(sizeof(xmlSchematronPattern));
493
+ if (ret == NULL) {
494
+ xmlSchematronPErrMemory(ctxt, "allocating schema pattern", node);
495
+ return (NULL);
496
+ }
497
+ memset(ret, 0, sizeof(xmlSchematronPattern));
498
+ ret->name = name;
499
+ ret->next = NULL;
500
+ if (schema->patterns == NULL) {
501
+ schema->patterns = ret;
502
+ } else {
503
+ xmlSchematronPatternPtr prev = schema->patterns;
504
+
505
+ while (prev->next != NULL)
506
+ prev = prev->next;
507
+ prev->next = ret;
508
+ }
509
+ return (ret);
510
+ }
511
+
512
+ /**
513
+ * xmlSchematronFreePatterns:
514
+ * @patterns: a list of patterns
515
+ *
516
+ * Free a list of patterns.
517
+ */
518
+ static void
519
+ xmlSchematronFreePatterns(xmlSchematronPatternPtr patterns) {
520
+ xmlSchematronPatternPtr next;
521
+
522
+ while (patterns != NULL) {
523
+ next = patterns->next;
524
+ if (patterns->name != NULL)
525
+ xmlFree(patterns->name);
526
+ xmlFree(patterns);
527
+ patterns = next;
528
+ }
529
+ }
530
+
531
+ /**
532
+ * xmlSchematronNewSchematron:
533
+ * @ctxt: a schema validation context
534
+ *
535
+ * Allocate a new Schematron structure.
536
+ *
537
+ * Returns the newly allocated structure or NULL in case or error
538
+ */
539
+ static xmlSchematronPtr
540
+ xmlSchematronNewSchematron(xmlSchematronParserCtxtPtr ctxt)
541
+ {
542
+ xmlSchematronPtr ret;
543
+
544
+ ret = (xmlSchematronPtr) xmlMalloc(sizeof(xmlSchematron));
545
+ if (ret == NULL) {
546
+ xmlSchematronPErrMemory(ctxt, "allocating schema", NULL);
547
+ return (NULL);
548
+ }
549
+ memset(ret, 0, sizeof(xmlSchematron));
550
+ ret->dict = ctxt->dict;
551
+ xmlDictReference(ret->dict);
552
+
553
+ return (ret);
554
+ }
555
+
556
+ /**
557
+ * xmlSchematronFree:
558
+ * @schema: a schema structure
559
+ *
560
+ * Deallocate a Schematron structure.
561
+ */
562
+ void
563
+ xmlSchematronFree(xmlSchematronPtr schema)
564
+ {
565
+ if (schema == NULL)
566
+ return;
567
+
568
+ if ((schema->doc != NULL) && (!(schema->preserve)))
569
+ xmlFreeDoc(schema->doc);
570
+
571
+ if (schema->namespaces != NULL)
572
+ xmlFree((char **) schema->namespaces);
573
+
574
+ xmlSchematronFreeRules(schema->rules);
575
+ xmlSchematronFreePatterns(schema->patterns);
576
+ xmlDictFree(schema->dict);
577
+ xmlFree(schema);
578
+ }
579
+
580
+ /**
581
+ * xmlSchematronNewParserCtxt:
582
+ * @URL: the location of the schema
583
+ *
584
+ * Create an XML Schematrons parse context for that file/resource expected
585
+ * to contain an XML Schematrons file.
586
+ *
587
+ * Returns the parser context or NULL in case of error
588
+ */
589
+ xmlSchematronParserCtxtPtr
590
+ xmlSchematronNewParserCtxt(const char *URL)
591
+ {
592
+ xmlSchematronParserCtxtPtr ret;
593
+
594
+ if (URL == NULL)
595
+ return (NULL);
596
+
597
+ ret =
598
+ (xmlSchematronParserCtxtPtr)
599
+ xmlMalloc(sizeof(xmlSchematronParserCtxt));
600
+ if (ret == NULL) {
601
+ xmlSchematronPErrMemory(NULL, "allocating schema parser context",
602
+ NULL);
603
+ return (NULL);
604
+ }
605
+ memset(ret, 0, sizeof(xmlSchematronParserCtxt));
606
+ ret->type = XML_STRON_CTXT_PARSER;
607
+ ret->dict = xmlDictCreate();
608
+ ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
609
+ ret->includes = NULL;
610
+ ret->xctxt = xmlXPathNewContext(NULL);
611
+ if (ret->xctxt == NULL) {
612
+ xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
613
+ NULL);
614
+ xmlSchematronFreeParserCtxt(ret);
615
+ return (NULL);
616
+ }
617
+ ret->xctxt->flags = XML_XPATH_CHECKNS;
618
+ return (ret);
619
+ }
620
+
621
+ /**
622
+ * xmlSchematronNewMemParserCtxt:
623
+ * @buffer: a pointer to a char array containing the schemas
624
+ * @size: the size of the array
625
+ *
626
+ * Create an XML Schematrons parse context for that memory buffer expected
627
+ * to contain an XML Schematrons file.
628
+ *
629
+ * Returns the parser context or NULL in case of error
630
+ */
631
+ xmlSchematronParserCtxtPtr
632
+ xmlSchematronNewMemParserCtxt(const char *buffer, int size)
633
+ {
634
+ xmlSchematronParserCtxtPtr ret;
635
+
636
+ if ((buffer == NULL) || (size <= 0))
637
+ return (NULL);
638
+
639
+ ret =
640
+ (xmlSchematronParserCtxtPtr)
641
+ xmlMalloc(sizeof(xmlSchematronParserCtxt));
642
+ if (ret == NULL) {
643
+ xmlSchematronPErrMemory(NULL, "allocating schema parser context",
644
+ NULL);
645
+ return (NULL);
646
+ }
647
+ memset(ret, 0, sizeof(xmlSchematronParserCtxt));
648
+ ret->buffer = buffer;
649
+ ret->size = size;
650
+ ret->dict = xmlDictCreate();
651
+ ret->xctxt = xmlXPathNewContext(NULL);
652
+ if (ret->xctxt == NULL) {
653
+ xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
654
+ NULL);
655
+ xmlSchematronFreeParserCtxt(ret);
656
+ return (NULL);
657
+ }
658
+ return (ret);
659
+ }
660
+
661
+ /**
662
+ * xmlSchematronNewDocParserCtxt:
663
+ * @doc: a preparsed document tree
664
+ *
665
+ * Create an XML Schematrons parse context for that document.
666
+ * NB. The document may be modified during the parsing process.
667
+ *
668
+ * Returns the parser context or NULL in case of error
669
+ */
670
+ xmlSchematronParserCtxtPtr
671
+ xmlSchematronNewDocParserCtxt(xmlDocPtr doc)
672
+ {
673
+ xmlSchematronParserCtxtPtr ret;
674
+
675
+ if (doc == NULL)
676
+ return (NULL);
677
+
678
+ ret =
679
+ (xmlSchematronParserCtxtPtr)
680
+ xmlMalloc(sizeof(xmlSchematronParserCtxt));
681
+ if (ret == NULL) {
682
+ xmlSchematronPErrMemory(NULL, "allocating schema parser context",
683
+ NULL);
684
+ return (NULL);
685
+ }
686
+ memset(ret, 0, sizeof(xmlSchematronParserCtxt));
687
+ ret->doc = doc;
688
+ ret->dict = xmlDictCreate();
689
+ /* The application has responsibility for the document */
690
+ ret->preserve = 1;
691
+ ret->xctxt = xmlXPathNewContext(doc);
692
+ if (ret->xctxt == NULL) {
693
+ xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
694
+ NULL);
695
+ xmlSchematronFreeParserCtxt(ret);
696
+ return (NULL);
697
+ }
698
+
699
+ return (ret);
700
+ }
701
+
702
+ /**
703
+ * xmlSchematronFreeParserCtxt:
704
+ * @ctxt: the schema parser context
705
+ *
706
+ * Free the resources associated to the schema parser context
707
+ */
708
+ void
709
+ xmlSchematronFreeParserCtxt(xmlSchematronParserCtxtPtr ctxt)
710
+ {
711
+ if (ctxt == NULL)
712
+ return;
713
+ if (ctxt->doc != NULL && !ctxt->preserve)
714
+ xmlFreeDoc(ctxt->doc);
715
+ if (ctxt->xctxt != NULL) {
716
+ xmlXPathFreeContext(ctxt->xctxt);
717
+ }
718
+ if (ctxt->namespaces != NULL)
719
+ xmlFree((char **) ctxt->namespaces);
720
+ xmlDictFree(ctxt->dict);
721
+ xmlFree(ctxt);
722
+ }
723
+
724
+ #if 0
725
+ /**
726
+ * xmlSchematronPushInclude:
727
+ * @ctxt: the schema parser context
728
+ * @doc: the included document
729
+ * @cur: the current include node
730
+ *
731
+ * Add an included document
732
+ */
733
+ static void
734
+ xmlSchematronPushInclude(xmlSchematronParserCtxtPtr ctxt,
735
+ xmlDocPtr doc, xmlNodePtr cur)
736
+ {
737
+ if (ctxt->includes == NULL) {
738
+ ctxt->maxIncludes = 10;
739
+ ctxt->includes = (xmlNodePtr *)
740
+ xmlMalloc(ctxt->maxIncludes * 2 * sizeof(xmlNodePtr));
741
+ if (ctxt->includes == NULL) {
742
+ xmlSchematronPErrMemory(NULL, "allocating parser includes",
743
+ NULL);
744
+ return;
745
+ }
746
+ ctxt->nbIncludes = 0;
747
+ } else if (ctxt->nbIncludes + 2 >= ctxt->maxIncludes) {
748
+ xmlNodePtr *tmp;
749
+
750
+ tmp = (xmlNodePtr *)
751
+ xmlRealloc(ctxt->includes, ctxt->maxIncludes * 4 *
752
+ sizeof(xmlNodePtr));
753
+ if (tmp == NULL) {
754
+ xmlSchematronPErrMemory(NULL, "allocating parser includes",
755
+ NULL);
756
+ return;
757
+ }
758
+ ctxt->includes = tmp;
759
+ ctxt->maxIncludes *= 2;
760
+ }
761
+ ctxt->includes[2 * ctxt->nbIncludes] = cur;
762
+ ctxt->includes[2 * ctxt->nbIncludes + 1] = (xmlNodePtr) doc;
763
+ ctxt->nbIncludes++;
764
+ }
765
+
766
+ /**
767
+ * xmlSchematronPopInclude:
768
+ * @ctxt: the schema parser context
769
+ *
770
+ * Pop an include level. The included document is being freed
771
+ *
772
+ * Returns the node immediately following the include or NULL if the
773
+ * include list was empty.
774
+ */
775
+ static xmlNodePtr
776
+ xmlSchematronPopInclude(xmlSchematronParserCtxtPtr ctxt)
777
+ {
778
+ xmlDocPtr doc;
779
+ xmlNodePtr ret;
780
+
781
+ if (ctxt->nbIncludes <= 0)
782
+ return(NULL);
783
+ ctxt->nbIncludes--;
784
+ doc = (xmlDocPtr) ctxt->includes[2 * ctxt->nbIncludes + 1];
785
+ ret = ctxt->includes[2 * ctxt->nbIncludes];
786
+ xmlFreeDoc(doc);
787
+ if (ret != NULL)
788
+ ret = ret->next;
789
+ if (ret == NULL)
790
+ return(xmlSchematronPopInclude(ctxt));
791
+ return(ret);
792
+ }
793
+ #endif
794
+
795
+ /**
796
+ * xmlSchematronAddNamespace:
797
+ * @ctxt: the schema parser context
798
+ * @prefix: the namespace prefix
799
+ * @ns: the namespace name
800
+ *
801
+ * Add a namespace definition in the context
802
+ */
803
+ static void
804
+ xmlSchematronAddNamespace(xmlSchematronParserCtxtPtr ctxt,
805
+ const xmlChar *prefix, const xmlChar *ns)
806
+ {
807
+ if (ctxt->namespaces == NULL) {
808
+ ctxt->maxNamespaces = 10;
809
+ ctxt->namespaces = (const xmlChar **)
810
+ xmlMalloc(ctxt->maxNamespaces * 2 * sizeof(const xmlChar *));
811
+ if (ctxt->namespaces == NULL) {
812
+ xmlSchematronPErrMemory(NULL, "allocating parser namespaces",
813
+ NULL);
814
+ return;
815
+ }
816
+ ctxt->nbNamespaces = 0;
817
+ } else if (ctxt->nbNamespaces + 2 >= ctxt->maxNamespaces) {
818
+ const xmlChar **tmp;
819
+
820
+ tmp = (const xmlChar **)
821
+ xmlRealloc((xmlChar **) ctxt->namespaces, ctxt->maxNamespaces * 4 *
822
+ sizeof(const xmlChar *));
823
+ if (tmp == NULL) {
824
+ xmlSchematronPErrMemory(NULL, "allocating parser namespaces",
825
+ NULL);
826
+ return;
827
+ }
828
+ ctxt->namespaces = tmp;
829
+ ctxt->maxNamespaces *= 2;
830
+ }
831
+ ctxt->namespaces[2 * ctxt->nbNamespaces] =
832
+ xmlDictLookup(ctxt->dict, ns, -1);
833
+ ctxt->namespaces[2 * ctxt->nbNamespaces + 1] =
834
+ xmlDictLookup(ctxt->dict, prefix, -1);
835
+ ctxt->nbNamespaces++;
836
+ ctxt->namespaces[2 * ctxt->nbNamespaces] = NULL;
837
+ ctxt->namespaces[2 * ctxt->nbNamespaces + 1] = NULL;
838
+
839
+ }
840
+
841
+ /**
842
+ * xmlSchematronParseRule:
843
+ * @ctxt: a schema validation context
844
+ * @rule: the rule node
845
+ *
846
+ * parse a rule element
847
+ */
848
+ static void
849
+ xmlSchematronParseRule(xmlSchematronParserCtxtPtr ctxt,
850
+ xmlSchematronPatternPtr pattern,
851
+ xmlNodePtr rule)
852
+ {
853
+ xmlNodePtr cur;
854
+ int nbChecks = 0;
855
+ xmlChar *test;
856
+ xmlChar *context;
857
+ xmlChar *report;
858
+ xmlSchematronRulePtr ruleptr;
859
+ xmlSchematronTestPtr testptr;
860
+
861
+ if ((ctxt == NULL) || (rule == NULL)) return;
862
+
863
+ context = xmlGetNoNsProp(rule, BAD_CAST "context");
864
+ if (context == NULL) {
865
+ xmlSchematronPErr(ctxt, rule,
866
+ XML_SCHEMAP_NOROOT,
867
+ "rule has no context attribute",
868
+ NULL, NULL);
869
+ return;
870
+ } else if (context[0] == 0) {
871
+ xmlSchematronPErr(ctxt, rule,
872
+ XML_SCHEMAP_NOROOT,
873
+ "rule has an empty context attribute",
874
+ NULL, NULL);
875
+ xmlFree(context);
876
+ return;
877
+ } else {
878
+ ruleptr = xmlSchematronAddRule(ctxt, ctxt->schema, pattern,
879
+ rule, context, NULL);
880
+ if (ruleptr == NULL) {
881
+ xmlFree(context);
882
+ return;
883
+ }
884
+ }
885
+
886
+ cur = rule->children;
887
+ NEXT_SCHEMATRON(cur);
888
+ while (cur != NULL) {
889
+ if (IS_SCHEMATRON(cur, "assert")) {
890
+ nbChecks++;
891
+ test = xmlGetNoNsProp(cur, BAD_CAST "test");
892
+ if (test == NULL) {
893
+ xmlSchematronPErr(ctxt, cur,
894
+ XML_SCHEMAP_NOROOT,
895
+ "assert has no test attribute",
896
+ NULL, NULL);
897
+ } else if (test[0] == 0) {
898
+ xmlSchematronPErr(ctxt, cur,
899
+ XML_SCHEMAP_NOROOT,
900
+ "assert has an empty test attribute",
901
+ NULL, NULL);
902
+ xmlFree(test);
903
+ } else {
904
+ /* TODO will need dynamic processing instead */
905
+ report = xmlNodeGetContent(cur);
906
+
907
+ testptr = xmlSchematronAddTest(ctxt, XML_SCHEMATRON_ASSERT,
908
+ ruleptr, cur, test, report);
909
+ if (testptr == NULL)
910
+ xmlFree(test);
911
+ }
912
+ } else if (IS_SCHEMATRON(cur, "report")) {
913
+ nbChecks++;
914
+ test = xmlGetNoNsProp(cur, BAD_CAST "test");
915
+ if (test == NULL) {
916
+ xmlSchematronPErr(ctxt, cur,
917
+ XML_SCHEMAP_NOROOT,
918
+ "assert has no test attribute",
919
+ NULL, NULL);
920
+ } else if (test[0] == 0) {
921
+ xmlSchematronPErr(ctxt, cur,
922
+ XML_SCHEMAP_NOROOT,
923
+ "assert has an empty test attribute",
924
+ NULL, NULL);
925
+ xmlFree(test);
926
+ } else {
927
+ /* TODO will need dynamic processing instead */
928
+ report = xmlNodeGetContent(cur);
929
+
930
+ testptr = xmlSchematronAddTest(ctxt, XML_SCHEMATRON_REPORT,
931
+ ruleptr, cur, test, report);
932
+ if (testptr == NULL)
933
+ xmlFree(test);
934
+ }
935
+ } else {
936
+ xmlSchematronPErr(ctxt, cur,
937
+ XML_SCHEMAP_NOROOT,
938
+ "Expecting an assert or a report element instead of %s",
939
+ cur->name, NULL);
940
+ }
941
+ cur = cur->next;
942
+ NEXT_SCHEMATRON(cur);
943
+ }
944
+ if (nbChecks == 0) {
945
+ xmlSchematronPErr(ctxt, rule,
946
+ XML_SCHEMAP_NOROOT,
947
+ "rule has no assert nor report element", NULL, NULL);
948
+ }
949
+ }
950
+
951
+ /**
952
+ * xmlSchematronParsePattern:
953
+ * @ctxt: a schema validation context
954
+ * @pat: the pattern node
955
+ *
956
+ * parse a pattern element
957
+ */
958
+ static void
959
+ xmlSchematronParsePattern(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr pat)
960
+ {
961
+ xmlNodePtr cur;
962
+ xmlSchematronPatternPtr pattern;
963
+ int nbRules = 0;
964
+ xmlChar *id;
965
+
966
+ if ((ctxt == NULL) || (pat == NULL)) return;
967
+
968
+ id = xmlGetNoNsProp(pat, BAD_CAST "id");
969
+ if (id == NULL) {
970
+ id = xmlGetNoNsProp(pat, BAD_CAST "name");
971
+ }
972
+ pattern = xmlSchematronAddPattern(ctxt, ctxt->schema, pat, id);
973
+ if (pattern == NULL) {
974
+ if (id != NULL)
975
+ xmlFree(id);
976
+ return;
977
+ }
978
+ cur = pat->children;
979
+ NEXT_SCHEMATRON(cur);
980
+ while (cur != NULL) {
981
+ if (IS_SCHEMATRON(cur, "rule")) {
982
+ xmlSchematronParseRule(ctxt, pattern, cur);
983
+ nbRules++;
984
+ } else {
985
+ xmlSchematronPErr(ctxt, cur,
986
+ XML_SCHEMAP_NOROOT,
987
+ "Expecting a rule element instead of %s", cur->name, NULL);
988
+ }
989
+ cur = cur->next;
990
+ NEXT_SCHEMATRON(cur);
991
+ }
992
+ if (nbRules == 0) {
993
+ xmlSchematronPErr(ctxt, pat,
994
+ XML_SCHEMAP_NOROOT,
995
+ "Pattern has no rule element", NULL, NULL);
996
+ }
997
+ }
998
+
999
+ #if 0
1000
+ /**
1001
+ * xmlSchematronLoadInclude:
1002
+ * @ctxt: a schema validation context
1003
+ * @cur: the include element
1004
+ *
1005
+ * Load the include document, Push the current pointer
1006
+ *
1007
+ * Returns the updated node pointer
1008
+ */
1009
+ static xmlNodePtr
1010
+ xmlSchematronLoadInclude(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr cur)
1011
+ {
1012
+ xmlNodePtr ret = NULL;
1013
+ xmlDocPtr doc = NULL;
1014
+ xmlChar *href = NULL;
1015
+ xmlChar *base = NULL;
1016
+ xmlChar *URI = NULL;
1017
+
1018
+ if ((ctxt == NULL) || (cur == NULL))
1019
+ return(NULL);
1020
+
1021
+ href = xmlGetNoNsProp(cur, BAD_CAST "href");
1022
+ if (href == NULL) {
1023
+ xmlSchematronPErr(ctxt, cur,
1024
+ XML_SCHEMAP_NOROOT,
1025
+ "Include has no href attribute", NULL, NULL);
1026
+ return(cur->next);
1027
+ }
1028
+
1029
+ /* do the URI base composition, load and find the root */
1030
+ base = xmlNodeGetBase(cur->doc, cur);
1031
+ URI = xmlBuildURI(href, base);
1032
+ doc = xmlReadFile((const char *) URI, NULL, SCHEMATRON_PARSE_OPTIONS);
1033
+ if (doc == NULL) {
1034
+ xmlSchematronPErr(ctxt, cur,
1035
+ XML_SCHEMAP_FAILED_LOAD,
1036
+ "could not load include '%s'.\n",
1037
+ URI, NULL);
1038
+ goto done;
1039
+ }
1040
+ ret = xmlDocGetRootElement(doc);
1041
+ if (ret == NULL) {
1042
+ xmlSchematronPErr(ctxt, cur,
1043
+ XML_SCHEMAP_FAILED_LOAD,
1044
+ "could not find root from include '%s'.\n",
1045
+ URI, NULL);
1046
+ goto done;
1047
+ }
1048
+
1049
+ /* Success, push the include for rollback on exit */
1050
+ xmlSchematronPushInclude(ctxt, doc, cur);
1051
+
1052
+ done:
1053
+ if (ret == NULL) {
1054
+ if (doc != NULL)
1055
+ xmlFreeDoc(doc);
1056
+ }
1057
+ xmlFree(href);
1058
+ if (base != NULL)
1059
+ xmlFree(base);
1060
+ if (URI != NULL)
1061
+ xmlFree(URI);
1062
+ return(ret);
1063
+ }
1064
+ #endif
1065
+
1066
+ /**
1067
+ * xmlSchematronParse:
1068
+ * @ctxt: a schema validation context
1069
+ *
1070
+ * parse a schema definition resource and build an internal
1071
+ * XML Schema structure which can be used to validate instances.
1072
+ *
1073
+ * Returns the internal XML Schematron structure built from the resource or
1074
+ * NULL in case of error
1075
+ */
1076
+ xmlSchematronPtr
1077
+ xmlSchematronParse(xmlSchematronParserCtxtPtr ctxt)
1078
+ {
1079
+ xmlSchematronPtr ret = NULL;
1080
+ xmlDocPtr doc;
1081
+ xmlNodePtr root, cur;
1082
+ int preserve = 0;
1083
+
1084
+ if (ctxt == NULL)
1085
+ return (NULL);
1086
+
1087
+ ctxt->nberrors = 0;
1088
+
1089
+ /*
1090
+ * First step is to parse the input document into an DOM/Infoset
1091
+ */
1092
+ if (ctxt->URL != NULL) {
1093
+ doc = xmlReadFile((const char *) ctxt->URL, NULL,
1094
+ SCHEMATRON_PARSE_OPTIONS);
1095
+ if (doc == NULL) {
1096
+ xmlSchematronPErr(ctxt, NULL,
1097
+ XML_SCHEMAP_FAILED_LOAD,
1098
+ "xmlSchematronParse: could not load '%s'.\n",
1099
+ ctxt->URL, NULL);
1100
+ return (NULL);
1101
+ }
1102
+ ctxt->preserve = 0;
1103
+ } else if (ctxt->buffer != NULL) {
1104
+ doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
1105
+ SCHEMATRON_PARSE_OPTIONS);
1106
+ if (doc == NULL) {
1107
+ xmlSchematronPErr(ctxt, NULL,
1108
+ XML_SCHEMAP_FAILED_PARSE,
1109
+ "xmlSchematronParse: could not parse.\n",
1110
+ NULL, NULL);
1111
+ return (NULL);
1112
+ }
1113
+ doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
1114
+ ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
1115
+ ctxt->preserve = 0;
1116
+ } else if (ctxt->doc != NULL) {
1117
+ doc = ctxt->doc;
1118
+ preserve = 1;
1119
+ ctxt->preserve = 1;
1120
+ } else {
1121
+ xmlSchematronPErr(ctxt, NULL,
1122
+ XML_SCHEMAP_NOTHING_TO_PARSE,
1123
+ "xmlSchematronParse: could not parse.\n",
1124
+ NULL, NULL);
1125
+ return (NULL);
1126
+ }
1127
+
1128
+ /*
1129
+ * Then extract the root and Schematron parse it
1130
+ */
1131
+ root = xmlDocGetRootElement(doc);
1132
+ if (root == NULL) {
1133
+ xmlSchematronPErr(ctxt, (xmlNodePtr) doc,
1134
+ XML_SCHEMAP_NOROOT,
1135
+ "The schema has no document element.\n", NULL, NULL);
1136
+ if (!preserve) {
1137
+ xmlFreeDoc(doc);
1138
+ }
1139
+ return (NULL);
1140
+ }
1141
+
1142
+ if (!IS_SCHEMATRON(root, "schema")) {
1143
+ xmlSchematronPErr(ctxt, root,
1144
+ XML_SCHEMAP_NOROOT,
1145
+ "The XML document '%s' is not a XML schematron document",
1146
+ ctxt->URL, NULL);
1147
+ goto exit;
1148
+ }
1149
+ ret = xmlSchematronNewSchematron(ctxt);
1150
+ if (ret == NULL)
1151
+ goto exit;
1152
+ ctxt->schema = ret;
1153
+
1154
+ /*
1155
+ * scan the schema elements
1156
+ */
1157
+ cur = root->children;
1158
+ NEXT_SCHEMATRON(cur);
1159
+ if (IS_SCHEMATRON(cur, "title")) {
1160
+ xmlChar *title = xmlNodeGetContent(cur);
1161
+ if (title != NULL) {
1162
+ ret->title = xmlDictLookup(ret->dict, title, -1);
1163
+ xmlFree(title);
1164
+ }
1165
+ cur = cur->next;
1166
+ NEXT_SCHEMATRON(cur);
1167
+ }
1168
+ while (IS_SCHEMATRON(cur, "ns")) {
1169
+ xmlChar *prefix = xmlGetNoNsProp(cur, BAD_CAST "prefix");
1170
+ xmlChar *uri = xmlGetNoNsProp(cur, BAD_CAST "uri");
1171
+ if ((uri == NULL) || (uri[0] == 0)) {
1172
+ xmlSchematronPErr(ctxt, cur,
1173
+ XML_SCHEMAP_NOROOT,
1174
+ "ns element has no uri", NULL, NULL);
1175
+ }
1176
+ if ((prefix == NULL) || (prefix[0] == 0)) {
1177
+ xmlSchematronPErr(ctxt, cur,
1178
+ XML_SCHEMAP_NOROOT,
1179
+ "ns element has no prefix", NULL, NULL);
1180
+ }
1181
+ if ((prefix) && (uri)) {
1182
+ xmlXPathRegisterNs(ctxt->xctxt, prefix, uri);
1183
+ xmlSchematronAddNamespace(ctxt, prefix, uri);
1184
+ ret->nbNs++;
1185
+ }
1186
+ if (uri)
1187
+ xmlFree(uri);
1188
+ if (prefix)
1189
+ xmlFree(prefix);
1190
+ cur = cur->next;
1191
+ NEXT_SCHEMATRON(cur);
1192
+ }
1193
+ while (cur != NULL) {
1194
+ if (IS_SCHEMATRON(cur, "pattern")) {
1195
+ xmlSchematronParsePattern(ctxt, cur);
1196
+ ret->nbPattern++;
1197
+ } else {
1198
+ xmlSchematronPErr(ctxt, cur,
1199
+ XML_SCHEMAP_NOROOT,
1200
+ "Expecting a pattern element instead of %s", cur->name, NULL);
1201
+ }
1202
+ cur = cur->next;
1203
+ NEXT_SCHEMATRON(cur);
1204
+ }
1205
+ if (ret->nbPattern == 0) {
1206
+ xmlSchematronPErr(ctxt, root,
1207
+ XML_SCHEMAP_NOROOT,
1208
+ "The schematron document '%s' has no pattern",
1209
+ ctxt->URL, NULL);
1210
+ goto exit;
1211
+ }
1212
+ /* the original document must be kept for reporting */
1213
+ ret->doc = doc;
1214
+ if (preserve) {
1215
+ ret->preserve = 1;
1216
+ }
1217
+ preserve = 1;
1218
+
1219
+ exit:
1220
+ if (!preserve) {
1221
+ xmlFreeDoc(doc);
1222
+ }
1223
+ if (ret != NULL) {
1224
+ if (ctxt->nberrors != 0) {
1225
+ xmlSchematronFree(ret);
1226
+ ret = NULL;
1227
+ } else {
1228
+ ret->namespaces = ctxt->namespaces;
1229
+ ret->nbNamespaces = ctxt->nbNamespaces;
1230
+ ctxt->namespaces = NULL;
1231
+ }
1232
+ }
1233
+ return (ret);
1234
+ }
1235
+
1236
+ /************************************************************************
1237
+ * *
1238
+ * Schematrontron Reports handler *
1239
+ * *
1240
+ ************************************************************************/
1241
+
1242
+ static xmlNodePtr
1243
+ xmlSchematronGetNode(xmlSchematronValidCtxtPtr ctxt,
1244
+ xmlNodePtr cur, const xmlChar *xpath) {
1245
+ xmlNodePtr node = NULL;
1246
+ xmlXPathObjectPtr ret;
1247
+
1248
+ if ((ctxt == NULL) || (cur == NULL) || (xpath == NULL))
1249
+ return(NULL);
1250
+
1251
+ ctxt->xctxt->doc = cur->doc;
1252
+ ctxt->xctxt->node = cur;
1253
+ ret = xmlXPathEval(xpath, ctxt->xctxt);
1254
+ if (ret == NULL)
1255
+ return(NULL);
1256
+
1257
+ if ((ret->type == XPATH_NODESET) &&
1258
+ (ret->nodesetval != NULL) && (ret->nodesetval->nodeNr > 0))
1259
+ node = ret->nodesetval->nodeTab[0];
1260
+
1261
+ xmlXPathFreeObject(ret);
1262
+ return(node);
1263
+ }
1264
+
1265
+ /**
1266
+ * xmlSchematronReportOutput:
1267
+ * @ctxt: the validation context
1268
+ * @cur: the current node tested
1269
+ * @msg: the message output
1270
+ *
1271
+ * Output part of the report to whatever channel the user selected
1272
+ */
1273
+ static void
1274
+ xmlSchematronReportOutput(xmlSchematronValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
1275
+ xmlNodePtr cur ATTRIBUTE_UNUSED,
1276
+ const char *msg) {
1277
+ /* TODO */
1278
+ fprintf(stderr, "%s", msg);
1279
+ }
1280
+
1281
+ /**
1282
+ * xmlSchematronFormatReport:
1283
+ * @ctxt: the validation context
1284
+ * @test: the test node
1285
+ * @cur: the current node tested
1286
+ *
1287
+ * Build the string being reported to the user.
1288
+ *
1289
+ * Returns a report string or NULL in case of error. The string needs
1290
+ * to be deallocated by the caller
1291
+ */
1292
+ static xmlChar *
1293
+ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
1294
+ xmlNodePtr test, xmlNodePtr cur) {
1295
+ xmlChar *ret = NULL;
1296
+ xmlNodePtr child, node;
1297
+
1298
+ if ((test == NULL) || (cur == NULL))
1299
+ return(ret);
1300
+
1301
+ child = test->children;
1302
+ while (child != NULL) {
1303
+ if ((child->type == XML_TEXT_NODE) ||
1304
+ (child->type == XML_CDATA_SECTION_NODE))
1305
+ ret = xmlStrcat(ret, child->content);
1306
+ else if (IS_SCHEMATRON(child, "name")) {
1307
+ xmlChar *path;
1308
+
1309
+ path = xmlGetNoNsProp(child, BAD_CAST "path");
1310
+
1311
+ node = cur;
1312
+ if (path != NULL) {
1313
+ node = xmlSchematronGetNode(ctxt, cur, path);
1314
+ if (node == NULL)
1315
+ node = cur;
1316
+ xmlFree(path);
1317
+ }
1318
+
1319
+ if ((node->ns == NULL) || (node->ns->prefix == NULL))
1320
+ ret = xmlStrcat(ret, node->name);
1321
+ else {
1322
+ ret = xmlStrcat(ret, node->ns->prefix);
1323
+ ret = xmlStrcat(ret, BAD_CAST ":");
1324
+ ret = xmlStrcat(ret, node->name);
1325
+ }
1326
+ } else {
1327
+ child = child->next;
1328
+ continue;
1329
+ }
1330
+
1331
+ /*
1332
+ * remove superfluous \n
1333
+ */
1334
+ if (ret != NULL) {
1335
+ int len = xmlStrlen(ret);
1336
+ xmlChar c;
1337
+
1338
+ if (len > 0) {
1339
+ c = ret[len - 1];
1340
+ if ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t')) {
1341
+ while ((c == ' ') || (c == '\n') ||
1342
+ (c == '\r') || (c == '\t')) {
1343
+ len--;
1344
+ if (len == 0)
1345
+ break;
1346
+ c = ret[len - 1];
1347
+ }
1348
+ ret[len] = ' ';
1349
+ ret[len + 1] = 0;
1350
+ }
1351
+ }
1352
+ }
1353
+
1354
+ child = child->next;
1355
+ }
1356
+ return(ret);
1357
+ }
1358
+
1359
+ /**
1360
+ * xmlSchematronReportSuccess:
1361
+ * @ctxt: the validation context
1362
+ * @test: the compiled test
1363
+ * @cur: the current node tested
1364
+ * @success: boolean value for the result
1365
+ *
1366
+ * called from the validation engine when an assert or report test have
1367
+ * been done.
1368
+ */
1369
+ static void
1370
+ xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt,
1371
+ xmlSchematronTestPtr test, xmlNodePtr cur, xmlSchematronPatternPtr pattern, int success) {
1372
+ if ((ctxt == NULL) || (cur == NULL) || (test == NULL))
1373
+ return;
1374
+ /* if quiet and not SVRL report only failures */
1375
+ if ((ctxt->flags & XML_SCHEMATRON_OUT_QUIET) &&
1376
+ ((ctxt->flags & XML_SCHEMATRON_OUT_XML) == 0) &&
1377
+ (test->type == XML_SCHEMATRON_REPORT))
1378
+ return;
1379
+ if (ctxt->flags & XML_SCHEMATRON_OUT_XML) {
1380
+ TODO
1381
+ } else {
1382
+ xmlChar *path;
1383
+ char msg[1000];
1384
+ long line;
1385
+ const xmlChar *report = NULL;
1386
+
1387
+ if (((test->type == XML_SCHEMATRON_REPORT) & (!success)) ||
1388
+ ((test->type == XML_SCHEMATRON_ASSERT) & (success)))
1389
+ return;
1390
+ line = xmlGetLineNo(cur);
1391
+ path = xmlGetNodePath(cur);
1392
+ if (path == NULL)
1393
+ path = (xmlChar *) cur->name;
1394
+ #if 0
1395
+ if ((test->report != NULL) && (test->report[0] != 0))
1396
+ report = test->report;
1397
+ #endif
1398
+ if (test->node != NULL)
1399
+ report = xmlSchematronFormatReport(ctxt, test->node, cur);
1400
+ if (report == NULL) {
1401
+ if (test->type == XML_SCHEMATRON_ASSERT) {
1402
+ report = xmlStrdup((const xmlChar *) "node failed assert");
1403
+ } else {
1404
+ report = xmlStrdup((const xmlChar *) "node failed report");
1405
+ }
1406
+ }
1407
+ snprintf(msg, 999, "%s line %ld: %s\n", (const char *) path,
1408
+ line, (const char *) report);
1409
+
1410
+ if (ctxt->flags & XML_SCHEMATRON_OUT_ERROR) {
1411
+ xmlStructuredErrorFunc schannel = NULL;
1412
+ xmlGenericErrorFunc channel = NULL;
1413
+ void *data = NULL;
1414
+
1415
+ if (ctxt != NULL) {
1416
+ if (ctxt->serror != NULL)
1417
+ schannel = ctxt->serror;
1418
+ else
1419
+ channel = ctxt->error;
1420
+ data = ctxt->userData;
1421
+ }
1422
+
1423
+ __xmlRaiseError(schannel, channel, data,
1424
+ NULL, cur, XML_FROM_SCHEMATRONV,
1425
+ (test->type == XML_SCHEMATRON_ASSERT)?XML_SCHEMATRONV_ASSERT:XML_SCHEMATRONV_REPORT,
1426
+ XML_ERR_ERROR, NULL, line,
1427
+ (pattern == NULL)?NULL:((const char *) pattern->name),
1428
+ (const char *) path,
1429
+ (const char *) report, 0, 0,
1430
+ "%s", msg);
1431
+ } else {
1432
+ xmlSchematronReportOutput(ctxt, cur, &msg[0]);
1433
+ }
1434
+
1435
+ xmlFree((char *) report);
1436
+
1437
+ if ((path != NULL) && (path != (xmlChar *) cur->name))
1438
+ xmlFree(path);
1439
+ }
1440
+ }
1441
+
1442
+ /**
1443
+ * xmlSchematronReportPattern:
1444
+ * @ctxt: the validation context
1445
+ * @pattern: the current pattern
1446
+ *
1447
+ * called from the validation engine when starting to check a pattern
1448
+ */
1449
+ static void
1450
+ xmlSchematronReportPattern(xmlSchematronValidCtxtPtr ctxt,
1451
+ xmlSchematronPatternPtr pattern) {
1452
+ if ((ctxt == NULL) || (pattern == NULL))
1453
+ return;
1454
+ if ((ctxt->flags & XML_SCHEMATRON_OUT_QUIET) || (ctxt->flags & XML_SCHEMATRON_OUT_ERROR)) /* Error gives pattern name as part of error */
1455
+ return;
1456
+ if (ctxt->flags & XML_SCHEMATRON_OUT_XML) {
1457
+ TODO
1458
+ } else {
1459
+ char msg[1000];
1460
+
1461
+ if (pattern->name == NULL)
1462
+ return;
1463
+ snprintf(msg, 999, "Pattern: %s\n", (const char *) pattern->name);
1464
+ xmlSchematronReportOutput(ctxt, NULL, &msg[0]);
1465
+ }
1466
+ }
1467
+
1468
+
1469
+ /************************************************************************
1470
+ * *
1471
+ * Validation against a Schematrontron *
1472
+ * *
1473
+ ************************************************************************/
1474
+
1475
+ /**
1476
+ * xmlSchematronSetValidStructuredErrors:
1477
+ * @ctxt: a Schematron validation context
1478
+ * @serror: the structured error function
1479
+ * @ctx: the functions context
1480
+ *
1481
+ * Set the structured error callback
1482
+ */
1483
+ void
1484
+ xmlSchematronSetValidStructuredErrors(xmlSchematronValidCtxtPtr ctxt,
1485
+ xmlStructuredErrorFunc serror, void *ctx)
1486
+ {
1487
+ if (ctxt == NULL)
1488
+ return;
1489
+ ctxt->serror = serror;
1490
+ ctxt->error = NULL;
1491
+ ctxt->warning = NULL;
1492
+ ctxt->userData = ctx;
1493
+ }
1494
+
1495
+ /**
1496
+ * xmlSchematronNewValidCtxt:
1497
+ * @schema: a precompiled XML Schematrons
1498
+ * @options: a set of xmlSchematronValidOptions
1499
+ *
1500
+ * Create an XML Schematrons validation context based on the given schema.
1501
+ *
1502
+ * Returns the validation context or NULL in case of error
1503
+ */
1504
+ xmlSchematronValidCtxtPtr
1505
+ xmlSchematronNewValidCtxt(xmlSchematronPtr schema, int options)
1506
+ {
1507
+ int i;
1508
+ xmlSchematronValidCtxtPtr ret;
1509
+
1510
+ ret = (xmlSchematronValidCtxtPtr) xmlMalloc(sizeof(xmlSchematronValidCtxt));
1511
+ if (ret == NULL) {
1512
+ xmlSchematronVErrMemory(NULL, "allocating validation context",
1513
+ NULL);
1514
+ return (NULL);
1515
+ }
1516
+ memset(ret, 0, sizeof(xmlSchematronValidCtxt));
1517
+ ret->type = XML_STRON_CTXT_VALIDATOR;
1518
+ ret->schema = schema;
1519
+ ret->xctxt = xmlXPathNewContext(NULL);
1520
+ ret->flags = options;
1521
+ if (ret->xctxt == NULL) {
1522
+ xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
1523
+ NULL);
1524
+ xmlSchematronFreeValidCtxt(ret);
1525
+ return (NULL);
1526
+ }
1527
+ for (i = 0;i < schema->nbNamespaces;i++) {
1528
+ if ((schema->namespaces[2 * i] == NULL) ||
1529
+ (schema->namespaces[2 * i + 1] == NULL))
1530
+ break;
1531
+ xmlXPathRegisterNs(ret->xctxt, schema->namespaces[2 * i + 1],
1532
+ schema->namespaces[2 * i]);
1533
+ }
1534
+ return (ret);
1535
+ }
1536
+
1537
+ /**
1538
+ * xmlSchematronFreeValidCtxt:
1539
+ * @ctxt: the schema validation context
1540
+ *
1541
+ * Free the resources associated to the schema validation context
1542
+ */
1543
+ void
1544
+ xmlSchematronFreeValidCtxt(xmlSchematronValidCtxtPtr ctxt)
1545
+ {
1546
+ if (ctxt == NULL)
1547
+ return;
1548
+ if (ctxt->xctxt != NULL)
1549
+ xmlXPathFreeContext(ctxt->xctxt);
1550
+ if (ctxt->dict != NULL)
1551
+ xmlDictFree(ctxt->dict);
1552
+ xmlFree(ctxt);
1553
+ }
1554
+
1555
+ static xmlNodePtr
1556
+ xmlSchematronNextNode(xmlNodePtr cur) {
1557
+ if (cur->children != NULL) {
1558
+ /*
1559
+ * Do not descend on entities declarations
1560
+ */
1561
+ if (cur->children->type != XML_ENTITY_DECL) {
1562
+ cur = cur->children;
1563
+ /*
1564
+ * Skip DTDs
1565
+ */
1566
+ if (cur->type != XML_DTD_NODE)
1567
+ return(cur);
1568
+ }
1569
+ }
1570
+
1571
+ while (cur->next != NULL) {
1572
+ cur = cur->next;
1573
+ if ((cur->type != XML_ENTITY_DECL) &&
1574
+ (cur->type != XML_DTD_NODE))
1575
+ return(cur);
1576
+ }
1577
+
1578
+ do {
1579
+ cur = cur->parent;
1580
+ if (cur == NULL) break;
1581
+ if (cur->type == XML_DOCUMENT_NODE) return(NULL);
1582
+ if (cur->next != NULL) {
1583
+ cur = cur->next;
1584
+ return(cur);
1585
+ }
1586
+ } while (cur != NULL);
1587
+ return(cur);
1588
+ }
1589
+
1590
+ /**
1591
+ * xmlSchematronRunTest:
1592
+ * @ctxt: the schema validation context
1593
+ * @test: the current test
1594
+ * @instance: the document instance tree
1595
+ * @cur: the current node in the instance
1596
+ *
1597
+ * Validate a rule against a tree instance at a given position
1598
+ *
1599
+ * Returns 1 in case of success, 0 if error and -1 in case of internal error
1600
+ */
1601
+ static int
1602
+ xmlSchematronRunTest(xmlSchematronValidCtxtPtr ctxt,
1603
+ xmlSchematronTestPtr test, xmlDocPtr instance, xmlNodePtr cur, xmlSchematronPatternPtr pattern)
1604
+ {
1605
+ xmlXPathObjectPtr ret;
1606
+ int failed;
1607
+
1608
+ failed = 0;
1609
+ ctxt->xctxt->doc = instance;
1610
+ ctxt->xctxt->node = cur;
1611
+ ret = xmlXPathCompiledEval(test->comp, ctxt->xctxt);
1612
+ if (ret == NULL) {
1613
+ failed = 1;
1614
+ } else {
1615
+ switch (ret->type) {
1616
+ case XPATH_XSLT_TREE:
1617
+ case XPATH_NODESET:
1618
+ if ((ret->nodesetval == NULL) ||
1619
+ (ret->nodesetval->nodeNr == 0))
1620
+ failed = 1;
1621
+ break;
1622
+ case XPATH_BOOLEAN:
1623
+ failed = !ret->boolval;
1624
+ break;
1625
+ case XPATH_NUMBER:
1626
+ if ((xmlXPathIsNaN(ret->floatval)) ||
1627
+ (ret->floatval == 0.0))
1628
+ failed = 1;
1629
+ break;
1630
+ case XPATH_STRING:
1631
+ if ((ret->stringval == NULL) ||
1632
+ (ret->stringval[0] == 0))
1633
+ failed = 1;
1634
+ break;
1635
+ case XPATH_UNDEFINED:
1636
+ case XPATH_POINT:
1637
+ case XPATH_RANGE:
1638
+ case XPATH_LOCATIONSET:
1639
+ case XPATH_USERS:
1640
+ failed = 1;
1641
+ break;
1642
+ }
1643
+ xmlXPathFreeObject(ret);
1644
+ }
1645
+ if ((failed) && (test->type == XML_SCHEMATRON_ASSERT))
1646
+ ctxt->nberrors++;
1647
+ else if ((!failed) && (test->type == XML_SCHEMATRON_REPORT))
1648
+ ctxt->nberrors++;
1649
+
1650
+ xmlSchematronReportSuccess(ctxt, test, cur, pattern, !failed);
1651
+
1652
+ return(!failed);
1653
+ }
1654
+
1655
+ /**
1656
+ * xmlSchematronValidateDoc:
1657
+ * @ctxt: the schema validation context
1658
+ * @instance: the document instance tree
1659
+ *
1660
+ * Validate a tree instance against the schematron
1661
+ *
1662
+ * Returns 0 in case of success, -1 in case of internal error
1663
+ * and an error count otherwise.
1664
+ */
1665
+ int
1666
+ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
1667
+ {
1668
+ xmlNodePtr cur, root;
1669
+ xmlSchematronPatternPtr pattern;
1670
+ xmlSchematronRulePtr rule;
1671
+ xmlSchematronTestPtr test;
1672
+
1673
+ if ((ctxt == NULL) || (ctxt->schema == NULL) ||
1674
+ (ctxt->schema->rules == NULL) || (instance == NULL))
1675
+ return(-1);
1676
+ ctxt->nberrors = 0;
1677
+ root = xmlDocGetRootElement(instance);
1678
+ if (root == NULL) {
1679
+ TODO
1680
+ ctxt->nberrors++;
1681
+ return(1);
1682
+ }
1683
+ if ((ctxt->flags & XML_SCHEMATRON_OUT_QUIET) ||
1684
+ (ctxt->flags == 0)) {
1685
+ /*
1686
+ * we are just trying to assert the validity of the document,
1687
+ * speed primes over the output, run in a single pass
1688
+ */
1689
+ cur = root;
1690
+ while (cur != NULL) {
1691
+ rule = ctxt->schema->rules;
1692
+ while (rule != NULL) {
1693
+ if (xmlPatternMatch(rule->pattern, cur) == 1) {
1694
+ test = rule->tests;
1695
+ while (test != NULL) {
1696
+ xmlSchematronRunTest(ctxt, test, instance, cur, (xmlSchematronPatternPtr)rule->pattern);
1697
+ test = test->next;
1698
+ }
1699
+ }
1700
+ rule = rule->next;
1701
+ }
1702
+
1703
+ cur = xmlSchematronNextNode(cur);
1704
+ }
1705
+ } else {
1706
+ /*
1707
+ * Process all contexts one at a time
1708
+ */
1709
+ pattern = ctxt->schema->patterns;
1710
+
1711
+ while (pattern != NULL) {
1712
+ xmlSchematronReportPattern(ctxt, pattern);
1713
+
1714
+ /*
1715
+ * TODO convert the pattern rule to a direct XPath and
1716
+ * compute directly instead of using the pattern matching
1717
+ * over the full document...
1718
+ * Check the exact semantic
1719
+ */
1720
+ cur = root;
1721
+ while (cur != NULL) {
1722
+ rule = pattern->rules;
1723
+ while (rule != NULL) {
1724
+ if (xmlPatternMatch(rule->pattern, cur) == 1) {
1725
+ test = rule->tests;
1726
+ while (test != NULL) {
1727
+ xmlSchematronRunTest(ctxt, test, instance, cur, pattern);
1728
+ test = test->next;
1729
+ }
1730
+ }
1731
+ rule = rule->patnext;
1732
+ }
1733
+
1734
+ cur = xmlSchematronNextNode(cur);
1735
+ }
1736
+ pattern = pattern->next;
1737
+ }
1738
+ }
1739
+ return(ctxt->nberrors);
1740
+ }
1741
+
1742
+ #ifdef STANDALONE
1743
+ int
1744
+ main(void)
1745
+ {
1746
+ int ret;
1747
+ xmlDocPtr instance;
1748
+ xmlSchematronParserCtxtPtr pctxt;
1749
+ xmlSchematronValidCtxtPtr vctxt;
1750
+ xmlSchematronPtr schema = NULL;
1751
+
1752
+ pctxt = xmlSchematronNewParserCtxt("tst.sct");
1753
+ if (pctxt == NULL) {
1754
+ fprintf(stderr, "failed to build schematron parser\n");
1755
+ } else {
1756
+ schema = xmlSchematronParse(pctxt);
1757
+ if (schema == NULL) {
1758
+ fprintf(stderr, "failed to compile schematron\n");
1759
+ }
1760
+ xmlSchematronFreeParserCtxt(pctxt);
1761
+ }
1762
+ instance = xmlReadFile("tst.sct", NULL,
1763
+ XML_PARSE_NOENT | XML_PARSE_NOCDATA);
1764
+ if (instance == NULL) {
1765
+ fprintf(stderr, "failed to parse instance\n");
1766
+ }
1767
+ if ((schema != NULL) && (instance != NULL)) {
1768
+ vctxt = xmlSchematronNewValidCtxt(schema);
1769
+ if (vctxt == NULL) {
1770
+ fprintf(stderr, "failed to build schematron validator\n");
1771
+ } else {
1772
+ ret = xmlSchematronValidateDoc(vctxt, instance);
1773
+ xmlSchematronFreeValidCtxt(vctxt);
1774
+ }
1775
+ }
1776
+ xmlSchematronFree(schema);
1777
+ xmlFreeDoc(instance);
1778
+
1779
+ xmlCleanupParser();
1780
+ xmlMemoryDump();
1781
+
1782
+ return (0);
1783
+ }
1784
+ #endif
1785
+ #define bottom_schematron
1786
+ #include "elfgcchack.h"
1787
+ #endif /* LIBXML_SCHEMATRON_ENABLED */