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