ReactOS  0.4.15-dev-3303-g1ade494
schematron.c
Go to the documentation of this file.
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
306 static xmlSchematronTestPtr
307 xmlSchematronAddTest(xmlSchematronParserCtxtPtr ctxt,
308  xmlSchematronTestType type,
309  xmlSchematronRulePtr rule,
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,
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 
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 
390 static xmlSchematronRulePtr
391 xmlSchematronAddRule(xmlSchematronParserCtxtPtr ctxt, xmlSchematronPtr schema,
392  xmlSchematronPatternPtr pat, xmlNodePtr node,
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,
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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,
867  "rule has no context attribute",
868  NULL, NULL);
869  return;
870  } else if (context[0] == 0) {
871  xmlSchematronPErr(ctxt, rule,
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,
895  "assert has no test attribute",
896  NULL, NULL);
897  } else if (test[0] == 0) {
898  xmlSchematronPErr(ctxt, cur,
900  "assert has an empty test attribute",
901  NULL, NULL);
902  xmlFree(test);
903  } else {
904  /* TODO will need dynamic processing instead */
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,
918  "assert has no test attribute",
919  NULL, NULL);
920  } else if (test[0] == 0) {
921  xmlSchematronPErr(ctxt, cur,
923  "assert has an empty test attribute",
924  NULL, NULL);
925  xmlFree(test);
926  } else {
927  /* TODO will need dynamic processing instead */
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,
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,
947  "rule has no assert nor report element", NULL, NULL);
948  }
949 }
950 
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,
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,
995  "Pattern has no rule element", NULL, NULL);
996  }
997 }
998 
999 #if 0
1000 
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,
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,
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,
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 
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,
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,
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,
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,
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,
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")) {
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,
1174  "ns element has no uri", NULL, NULL);
1175  }
1176  if ((prefix == NULL) || (prefix[0] == 0)) {
1177  xmlSchematronPErr(ctxt, cur,
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,
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,
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 
1273 static void
1274 xmlSchematronReportOutput(xmlSchematronValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
1276  const char *msg) {
1277  /* TODO */
1278  fprintf(stderr, "%s", msg);
1279 }
1280 
1292 static xmlChar *
1293 xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
1295  xmlChar *ret = NULL;
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 
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,
1425  (test->type == XML_SCHEMATRON_ASSERT)?XML_SCHEMATRONV_ASSERT:XML_SCHEMATRONV_REPORT,
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 
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 
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 
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 
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 
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 
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;
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;
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,
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);
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 */
XMLPUBFUN int XMLCALL xmlDictReference(xmlDictPtr dict)
Definition: dict.c:645
const xmlChar * URL
Definition: tree.h:577
#define error(str)
Definition: mkdosfs.c:1605
XMLPUBFUN xmlChar *XMLCALL xmlGetNoNsProp(const xmlNode *node, const xmlChar *name)
Definition: http.c:7251
GLsizei const GLchar ** path
Definition: glext.h:7234
const char * uri
Definition: sec_mgr.c:1588
static struct test_info tests[]
int main(int argc, char *argv[])
Definition: atactl.cpp:1685
XMLPUBFUN xmlDictPtr XMLCALL xmlDictCreate(void)
Definition: dict.c:575
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:425
struct _root root
#define snprintf
Definition: wintirpc.h:48
GLuint buffer
Definition: glext.h:5915
#define test
Definition: rosglue.h:37
XMLPUBFUN xmlDocPtr XMLCALL xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
Definition: parser.c:15245
XMLPUBFUN xmlChar *XMLCALL xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur)
if(dx==0 &&dy==0)
Definition: linetemp.h:174
static HWND child
Definition: cursoricon.c:298
struct _xmlDoc * doc
Definition: tree.h:560
struct node node
XMLPUBFUN xmlDocPtr XMLCALL xmlReadFile(const char *URL, const char *encoding, int options)
Definition: parser.c:15221
#define TODO
Definition: SAX2.c:49
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:529
XMLPUBFUN xmlChar *XMLCALL xmlBuildURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:1891
Definition: parser.c:48
xmlNode * xmlNodePtr
Definition: tree.h:488
GLuint GLsizei const GLvoid GLenum preserve
Definition: glext.h:9550
#define BAD_CAST
Definition: xmlstring.h:35
static void report(const DATA_BLOB *pDataIn, const DATA_BLOB *pOptionalEntropy, CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct, DWORD dwFlags)
Definition: protectdata.c:769
Definition: dict.c:116
int options
Definition: main.c:106
XMLPUBFUN long XMLCALL xmlGetLineNo(const xmlNode *node)
XMLPUBVAR xmlReallocFunc xmlRealloc
Definition: globals.h:249
#define LIBXML_ATTR_FORMAT(fmt, args)
Definition: xmlversion.h:477
static struct loaded_include * includes
Definition: compiler.c:53
GLsizeiptr size
Definition: glext.h:5919
Definition: id3.c:95
const GLubyte * c
Definition: glext.h:8905
char * name
Definition: compiler.c:66
XMLPUBFUN void XMLCALL xmlFreeDoc(xmlDocPtr cur)
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:250
#define success(from, fromstr, to, tostr)
XMLPUBFUN const xmlChar *XMLCALL xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:865
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
_In_opt_ PVOID _In_ ULONG _In_ PVOID context
Definition: wdfdriver.h:113
GLbitfield flags
Definition: glext.h:7161
XMLPUBFUN void XMLCALL xmlMemoryDump(void)
Definition: xmlmemory.c:931
Definition: tree.h:489
int ret
Definition: mxnamespace.c:44
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN void XMLCALL xmlDictFree(xmlDictPtr dict)
Definition: dict.c:800
GLenum GLsizei len
Definition: glext.h:6722
#define err(...)
IN PCTCH line
Definition: pager.h:36
FxCollectionEntry * cur
xmlDoc * xmlDocPtr
Definition: tree.h:550
static unsigned __int64 next
Definition: rand_nt.c:6
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
XMLPUBFUN xmlChar *XMLCALL xmlNodeGetContent(const xmlNode *cur)
struct define * next
Definition: compiler.c:65
static HINSTANCE instance
Definition: main.c:40
#define ATTRIBUTE_UNUSED
Definition: win32config.h:132
#define NULL
Definition: types.h:112
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:247
const WCHAR * schema
Definition: tree.h:551
#define msg(x)
Definition: auth_time.c:54
struct _xmlNode * children
Definition: tree.h:493
Definition: name.c:38
void(XMLCDECL * xmlGenericErrorFunc)(void *ctx, const char *msg,...) LIBXML_ATTR_FORMAT(2
Definition: xmlerror.h:845
XMLPUBFUN xmlNodePtr XMLCALL xmlDocGetRootElement(const xmlDoc *doc)
#define c
Definition: ke_i.h:80
GLenum GLuint id
Definition: glext.h:5579
FILE * stderr
#define const
Definition: zconf.h:230
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
void exit(int exitcode)
Definition: _exit.c:33
XMLPUBFUN void XMLCALL xmlCleanupParser(void)
Definition: parser.c:14732
#define memset(x, y, z)
Definition: compat.h:39
static char title[]
Definition: ps.c:92
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:66
#define warning(s)
Definition: debug.h:83
GLubyte * pattern
Definition: glext.h:7787
Definition: dlist.c:348
GLuint const GLchar * name
Definition: glext.h:6031