blob: f64c1b5e8eb07fe0f656a0905931dd6816a1927d [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
10#define IN_LIBXML
11#include "libxml.h"
12
13#ifdef LIBXML_SCHEMAS_ENABLED
14
15#include <string.h>
16#include <libxml/xmlmemory.h>
17#include <libxml/parser.h>
18#include <libxml/parserInternals.h>
19#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000020#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000021
22#include <libxml/xmlschemas.h>
23#include <libxml/schemasInternals.h>
24#include <libxml/xmlschemastypes.h>
25#include <libxml/xmlautomata.h>
26#include <libxml/xmlregexp.h>
27
Daniel Veillarda84c0b32003-06-02 16:58:46 +000028/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000029
Daniel Veillard82bbbd42003-05-11 20:16:09 +000030/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000031
Daniel Veillard82bbbd42003-05-11 20:16:09 +000032/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000033
Daniel Veillard118aed72002-09-24 14:13:13 +000034/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000035
Daniel Veillard4255d502002-04-16 15:50:10 +000036/* #define DEBUG_AUTOMATA 1 */
37
38#define UNBOUNDED (1 << 30)
39#define TODO \
40 xmlGenericError(xmlGenericErrorContext, \
41 "Unimplemented block at %s:%d\n", \
42 __FILE__, __LINE__);
43
Daniel Veillard5a872412002-05-22 06:40:27 +000044#define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
45
Daniel Veillard4255d502002-04-16 15:50:10 +000046/*
47 * The XML Schemas namespaces
48 */
49static const xmlChar *xmlSchemaNs = (const xmlChar *)
50 "http://www.w3.org/2001/XMLSchema";
51
52static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
53 "http://www.w3.org/2001/XMLSchema-instance";
54
55#define IS_SCHEMA(node, type) \
56 ((node != NULL) && (node->ns != NULL) && \
57 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
58 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
59
60#define XML_SCHEMAS_PARSE_ERROR 1
61
62struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000063 void *userData; /* user specific data block */
64 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
65 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +000066 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000067 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +000068 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +000069
Daniel Veillardd0c9c322003-10-10 00:49:42 +000070 xmlSchemaPtr schema; /* The schema in use */
71 xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +000072 int counter;
73
Daniel Veillardd0c9c322003-10-10 00:49:42 +000074 xmlChar *URL;
75 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +000076
Daniel Veillardd0c9c322003-10-10 00:49:42 +000077 const char *buffer;
78 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +000079
Daniel Veillard4255d502002-04-16 15:50:10 +000080 /*
81 * Used to build complex element content models
82 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000083 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +000084 xmlAutomataStatePtr start;
85 xmlAutomataStatePtr end;
86 xmlAutomataStatePtr state;
87};
88
89
90#define XML_SCHEMAS_ATTR_UNKNOWN 1
91#define XML_SCHEMAS_ATTR_CHECKED 2
92
93typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
94typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
95struct _xmlSchemaAttrState {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000096 xmlAttrPtr attr;
97 int state;
Daniel Veillard4255d502002-04-16 15:50:10 +000098};
99
100/**
101 * xmlSchemaValidCtxt:
102 *
103 * A Schemas validation context
104 */
105
106struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000107 void *userData; /* user specific data block */
108 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
109 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000110 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000111
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000112 xmlSchemaPtr schema; /* The schema in use */
113 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000114 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000115 xmlCharEncoding enc;
116 xmlSAXHandlerPtr sax;
117 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000118
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000119 xmlDocPtr myDoc;
120 int err;
121 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000122
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000123 xmlNodePtr node;
124 xmlNodePtr cur;
125 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000126
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000127 xmlRegExecCtxtPtr regexp;
128 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000129
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000130 int attrNr;
131 int attrBase;
132 int attrMax;
133 xmlSchemaAttrStatePtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +0000134};
135
136
137/************************************************************************
138 * *
139 * Some predeclarations *
140 * *
141 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000142static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
143 xmlSchemaTypePtr type,
144 xmlChar * value);
145
146/************************************************************************
147 * *
148 * Datatype error handlers *
149 * *
150 ************************************************************************/
151
152/**
153 * xmlSchemaPErrMemory:
154 * @node: a context node
155 * @extra: extra informations
156 *
157 * Handle an out of memory condition
158 */
159static void
160xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
161 const char *extra, xmlNodePtr node)
162{
163 if (ctxt != NULL)
164 ctxt->nberrors++;
165 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
166 extra);
167}
168
169/**
170 * xmlSchemaPErr:
171 * @ctxt: the parsing context
172 * @node: the context node
173 * @error: the error code
174 * @msg: the error message
175 * @str1: extra data
176 * @str2: extra data
177 *
178 * Handle a parser error
179 */
180static void
181xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
182 const char *msg, const xmlChar * str1, const xmlChar * str2)
183{
184 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000185 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000186 void *data = NULL;
187
188 if (ctxt != NULL) {
189 ctxt->nberrors++;
190 channel = ctxt->error;
191 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000192 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000193 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000194 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000195 error, XML_ERR_ERROR, NULL, 0,
196 (const char *) str1, (const char *) str2, NULL, 0, 0,
197 msg, str1, str2);
198}
199
200/**
201 * xmlSchemaPErr2:
202 * @ctxt: the parsing context
203 * @node: the context node
204 * @node: the current child
205 * @error: the error code
206 * @msg: the error message
207 * @str1: extra data
208 * @str2: extra data
209 *
210 * Handle a parser error
211 */
212static void
213xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
214 xmlNodePtr child, int error,
215 const char *msg, const xmlChar * str1, const xmlChar * str2)
216{
217 if (child != NULL)
218 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
219 else
220 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
221}
222
223/**
224 * xmlSchemaVTypeErrMemory:
225 * @node: a context node
226 * @extra: extra informations
227 *
228 * Handle an out of memory condition
229 */
230static void
231xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
232 const char *extra, xmlNodePtr node)
233{
234 if (ctxt != NULL) {
235 ctxt->nberrors++;
236 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
237 }
238 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
239 extra);
240}
241
242/**
243 * xmlSchemaVErr3:
244 * @ctxt: the validation context
245 * @node: the context node
246 * @error: the error code
247 * @msg: the error message
248 * @str1: extra data
249 * @str2: extra data
250 * @str3: extra data
251 *
252 * Handle a validation error
253 */
254static void
255xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
256 const char *msg, const xmlChar *str1, const xmlChar *str2,
257 const xmlChar *str3)
258{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000259 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000260 xmlGenericErrorFunc channel = NULL;
261 void *data = NULL;
262
263 if (ctxt != NULL) {
264 ctxt->nberrors++;
265 ctxt->err = error;
266 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000267 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000268 data = ctxt->userData;
269 }
270 /* reajust to global error numbers */
271 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000272 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000273 error, XML_ERR_ERROR, NULL, 0,
274 (const char *) str1, (const char *) str2,
275 (const char *) str3, 0, 0,
276 msg, str1, str2, str3);
277}
278/**
279 * xmlSchemaVErr:
280 * @ctxt: the validation context
281 * @node: the context node
282 * @error: the error code
283 * @msg: the error message
284 * @str1: extra data
285 * @str2: extra data
286 *
287 * Handle a validation error
288 */
289static void
290xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
291 const char *msg, const xmlChar * str1, const xmlChar * str2)
292{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000293 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000294 xmlGenericErrorFunc channel = NULL;
295 void *data = NULL;
296
297 if (ctxt != NULL) {
298 ctxt->nberrors++;
299 ctxt->err = error;
300 channel = ctxt->error;
301 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000302 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000303 }
304 /* reajust to global error numbers */
305 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000306 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000307 error, XML_ERR_ERROR, NULL, 0,
308 (const char *) str1, (const char *) str2, NULL, 0, 0,
309 msg, str1, str2);
310}
Daniel Veillard4255d502002-04-16 15:50:10 +0000311
312/************************************************************************
313 * *
314 * Allocation functions *
315 * *
316 ************************************************************************/
317
318/**
319 * xmlSchemaNewSchema:
320 * @ctxt: a schema validation context (optional)
321 *
322 * Allocate a new Schema structure.
323 *
324 * Returns the newly allocated structure or NULL in case or error
325 */
326static xmlSchemaPtr
327xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
328{
329 xmlSchemaPtr ret;
330
331 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
332 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000333 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000334 return (NULL);
335 }
336 memset(ret, 0, sizeof(xmlSchema));
337
338 return (ret);
339}
340
341/**
342 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000343 *
344 * Allocate a new Facet structure.
345 *
346 * Returns the newly allocated structure or NULL in case or error
347 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000348xmlSchemaFacetPtr
349xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000350{
351 xmlSchemaFacetPtr ret;
352
353 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
354 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000355 return (NULL);
356 }
357 memset(ret, 0, sizeof(xmlSchemaFacet));
358
359 return (ret);
360}
361
362/**
363 * xmlSchemaNewAnnot:
364 * @ctxt: a schema validation context (optional)
365 * @node: a node
366 *
367 * Allocate a new annotation structure.
368 *
369 * Returns the newly allocated structure or NULL in case or error
370 */
371static xmlSchemaAnnotPtr
372xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
373{
374 xmlSchemaAnnotPtr ret;
375
376 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
377 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000378 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000379 return (NULL);
380 }
381 memset(ret, 0, sizeof(xmlSchemaAnnot));
382 ret->content = node;
383 return (ret);
384}
385
386/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000387 * xmlSchemaFreeAnnot:
388 * @annot: a schema type structure
389 *
390 * Deallocate a annotation structure
391 */
392static void
393xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
394{
395 if (annot == NULL)
396 return;
397 xmlFree(annot);
398}
399
400/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000401 * xmlSchemaFreeNotation:
402 * @schema: a schema notation structure
403 *
404 * Deallocate a Schema Notation structure.
405 */
406static void
407xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
408{
409 if (nota == NULL)
410 return;
411 if (nota->name != NULL)
412 xmlFree((xmlChar *) nota->name);
413 xmlFree(nota);
414}
415
416/**
417 * xmlSchemaFreeAttribute:
418 * @schema: a schema attribute structure
419 *
420 * Deallocate a Schema Attribute structure.
421 */
422static void
423xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
424{
425 if (attr == NULL)
426 return;
427 if (attr->name != NULL)
428 xmlFree((xmlChar *) attr->name);
429 if (attr->ref != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000430 xmlFree((xmlChar *) attr->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000431 if (attr->refNs != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000432 xmlFree((xmlChar *) attr->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +0000433 if (attr->typeName != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000434 xmlFree((xmlChar *) attr->typeName);
Daniel Veillard4255d502002-04-16 15:50:10 +0000435 if (attr->typeNs != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000436 xmlFree((xmlChar *) attr->typeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +0000437 xmlFree(attr);
438}
439
440/**
441 * xmlSchemaFreeAttributeGroup:
442 * @schema: a schema attribute group structure
443 *
444 * Deallocate a Schema Attribute Group structure.
445 */
446static void
447xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
448{
449 if (attr == NULL)
450 return;
451 if (attr->name != NULL)
452 xmlFree((xmlChar *) attr->name);
Daniel Veillard91a13252003-03-27 23:44:43 +0000453 if (attr->ref != NULL)
454 xmlFree((xmlChar *) attr->ref);
455 if (attr->refNs != NULL)
456 xmlFree((xmlChar *) attr->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +0000457 xmlFree(attr);
458}
459
460/**
461 * xmlSchemaFreeElement:
462 * @schema: a schema element structure
463 *
464 * Deallocate a Schema Element structure.
465 */
466static void
467xmlSchemaFreeElement(xmlSchemaElementPtr elem)
468{
469 if (elem == NULL)
470 return;
471 if (elem->name != NULL)
472 xmlFree((xmlChar *) elem->name);
473 if (elem->namedType != NULL)
474 xmlFree((xmlChar *) elem->namedType);
475 if (elem->namedTypeNs != NULL)
476 xmlFree((xmlChar *) elem->namedTypeNs);
477 if (elem->ref != NULL)
478 xmlFree((xmlChar *) elem->ref);
479 if (elem->refNs != NULL)
480 xmlFree((xmlChar *) elem->refNs);
Daniel Veillard32370232002-10-16 14:08:14 +0000481 if (elem->annot != NULL)
482 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000483 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000484 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000485 xmlFree(elem);
486}
487
488/**
489 * xmlSchemaFreeFacet:
490 * @facet: a schema facet structure
491 *
492 * Deallocate a Schema Facet structure.
493 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000494void
Daniel Veillard4255d502002-04-16 15:50:10 +0000495xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
496{
497 if (facet == NULL)
498 return;
499 if (facet->value != NULL)
500 xmlFree((xmlChar *) facet->value);
501 if (facet->id != NULL)
502 xmlFree((xmlChar *) facet->id);
503 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000504 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000505 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000506 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000507 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000508 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000509 xmlFree(facet);
510}
511
512/**
513 * xmlSchemaFreeType:
514 * @type: a schema type structure
515 *
516 * Deallocate a Schema Type structure.
517 */
518void
519xmlSchemaFreeType(xmlSchemaTypePtr type)
520{
521 if (type == NULL)
522 return;
523 if (type->name != NULL)
524 xmlFree((xmlChar *) type->name);
525 if (type->base != NULL)
526 xmlFree((xmlChar *) type->base);
527 if (type->baseNs != NULL)
528 xmlFree((xmlChar *) type->baseNs);
529 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000530 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000531 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000532 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000533
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000534 facet = type->facets;
535 while (facet != NULL) {
536 next = facet->next;
537 xmlSchemaFreeFacet(facet);
538 facet = next;
539 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000540 }
541 xmlFree(type);
542}
543
544/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000545 * xmlSchemaFree:
546 * @schema: a schema structure
547 *
548 * Deallocate a Schema structure.
549 */
550void
551xmlSchemaFree(xmlSchemaPtr schema)
552{
553 if (schema == NULL)
554 return;
555
Daniel Veillard91a13252003-03-27 23:44:43 +0000556 if (schema->id != NULL)
557 xmlFree((xmlChar *) schema->id);
558 if (schema->targetNamespace != NULL)
559 xmlFree((xmlChar *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000560 if (schema->name != NULL)
561 xmlFree((xmlChar *) schema->name);
562 if (schema->notaDecl != NULL)
563 xmlHashFree(schema->notaDecl,
564 (xmlHashDeallocator) xmlSchemaFreeNotation);
565 if (schema->attrDecl != NULL)
566 xmlHashFree(schema->attrDecl,
567 (xmlHashDeallocator) xmlSchemaFreeAttribute);
568 if (schema->attrgrpDecl != NULL)
569 xmlHashFree(schema->attrgrpDecl,
570 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
571 if (schema->elemDecl != NULL)
572 xmlHashFree(schema->elemDecl,
573 (xmlHashDeallocator) xmlSchemaFreeElement);
574 if (schema->typeDecl != NULL)
575 xmlHashFree(schema->typeDecl,
576 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000577 if (schema->groupDecl != NULL)
578 xmlHashFree(schema->groupDecl,
579 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard4255d502002-04-16 15:50:10 +0000580 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000581 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000582 if (schema->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000583 xmlFreeDoc(schema->doc);
Daniel Veillard4255d502002-04-16 15:50:10 +0000584
585 xmlFree(schema);
586}
587
588/************************************************************************
589 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000590 * Debug functions *
591 * *
592 ************************************************************************/
593
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000594#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000595
Daniel Veillard4255d502002-04-16 15:50:10 +0000596/**
597 * xmlSchemaElementDump:
598 * @elem: an element
599 * @output: the file output
600 *
601 * Dump the element
602 */
603static void
604xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000605 const xmlChar * name ATTRIBUTE_UNUSED,
606 const xmlChar * context ATTRIBUTE_UNUSED,
607 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000608{
609 if (elem == NULL)
610 return;
611
612 fprintf(output, "Element ");
613 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000614 fprintf(output, "toplevel ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000615 fprintf(output, ": %s ", elem->name);
616 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 fprintf(output, "namespace '%s' ", namespace);
618
Daniel Veillard4255d502002-04-16 15:50:10 +0000619 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000620 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000621 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000623 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000624 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000625 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000626 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000627 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000629 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000630 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000631 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000632 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000633 fprintf(output, "\n");
634 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000635 fprintf(output, " ");
636 if (elem->minOccurs != 1)
637 fprintf(output, "min: %d ", elem->minOccurs);
638 if (elem->maxOccurs >= UNBOUNDED)
639 fprintf(output, "max: unbounded\n");
640 else if (elem->maxOccurs != 1)
641 fprintf(output, "max: %d\n", elem->maxOccurs);
642 else
643 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000644 }
645 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000646 fprintf(output, " type: %s", elem->namedType);
647 if (elem->namedTypeNs != NULL)
648 fprintf(output, " ns %s\n", elem->namedTypeNs);
649 else
650 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000651 }
652 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000653 fprintf(output, " substitutionGroup: %s", elem->substGroup);
654 if (elem->substGroupNs != NULL)
655 fprintf(output, " ns %s\n", elem->substGroupNs);
656 else
657 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000658 }
659 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000660 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000661}
662
663/**
664 * xmlSchemaAnnotDump:
665 * @output: the file output
666 * @annot: a annotation
667 *
668 * Dump the annotation
669 */
670static void
671xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
672{
673 xmlChar *content;
674
675 if (annot == NULL)
676 return;
677
678 content = xmlNodeGetContent(annot->content);
679 if (content != NULL) {
680 fprintf(output, " Annot: %s\n", content);
681 xmlFree(content);
682 } else
683 fprintf(output, " Annot: empty\n");
684}
685
686/**
687 * xmlSchemaTypeDump:
688 * @output: the file output
689 * @type: a type structure
690 *
691 * Dump a SchemaType structure
692 */
693static void
694xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
695{
696 if (type == NULL) {
697 fprintf(output, "Type: NULL\n");
698 return;
699 }
700 fprintf(output, "Type: ");
701 if (type->name != NULL)
702 fprintf(output, "%s, ", type->name);
703 else
704 fprintf(output, "no name");
705 switch (type->type) {
706 case XML_SCHEMA_TYPE_BASIC:
707 fprintf(output, "basic ");
708 break;
709 case XML_SCHEMA_TYPE_SIMPLE:
710 fprintf(output, "simple ");
711 break;
712 case XML_SCHEMA_TYPE_COMPLEX:
713 fprintf(output, "complex ");
714 break;
715 case XML_SCHEMA_TYPE_SEQUENCE:
716 fprintf(output, "sequence ");
717 break;
718 case XML_SCHEMA_TYPE_CHOICE:
719 fprintf(output, "choice ");
720 break;
721 case XML_SCHEMA_TYPE_ALL:
722 fprintf(output, "all ");
723 break;
724 case XML_SCHEMA_TYPE_UR:
725 fprintf(output, "ur ");
726 break;
727 case XML_SCHEMA_TYPE_RESTRICTION:
728 fprintf(output, "restriction ");
729 break;
730 case XML_SCHEMA_TYPE_EXTENSION:
731 fprintf(output, "extension ");
732 break;
733 default:
734 fprintf(output, "unknowntype%d ", type->type);
735 break;
736 }
737 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000738 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000739 }
740 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000741 case XML_SCHEMA_CONTENT_UNKNOWN:
742 fprintf(output, "unknown ");
743 break;
744 case XML_SCHEMA_CONTENT_EMPTY:
745 fprintf(output, "empty ");
746 break;
747 case XML_SCHEMA_CONTENT_ELEMENTS:
748 fprintf(output, "element ");
749 break;
750 case XML_SCHEMA_CONTENT_MIXED:
751 fprintf(output, "mixed ");
752 break;
753 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
754 fprintf(output, "mixed_or_elems ");
755 break;
756 case XML_SCHEMA_CONTENT_BASIC:
757 fprintf(output, "basic ");
758 break;
759 case XML_SCHEMA_CONTENT_SIMPLE:
760 fprintf(output, "simple ");
761 break;
762 case XML_SCHEMA_CONTENT_ANY:
763 fprintf(output, "any ");
764 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000765 }
766 fprintf(output, "\n");
767 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000768 fprintf(output, " ");
769 if (type->minOccurs != 1)
770 fprintf(output, "min: %d ", type->minOccurs);
771 if (type->maxOccurs >= UNBOUNDED)
772 fprintf(output, "max: unbounded\n");
773 else if (type->maxOccurs != 1)
774 fprintf(output, "max: %d\n", type->maxOccurs);
775 else
776 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000777 }
778 if (type->annot != NULL)
779 xmlSchemaAnnotDump(output, type->annot);
780 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000781 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000782
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000783 fprintf(output, " subtypes: ");
784 while (sub != NULL) {
785 fprintf(output, "%s ", sub->name);
786 sub = sub->next;
787 }
788 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000789 }
790
791}
792
793/**
794 * xmlSchemaDump:
795 * @output: the file output
796 * @schema: a schema structure
797 *
798 * Dump a Schema structure.
799 */
800void
801xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
802{
803 if (schema == NULL) {
804 fprintf(output, "Schemas: NULL\n");
805 return;
806 }
807 fprintf(output, "Schemas: ");
808 if (schema->name != NULL)
809 fprintf(output, "%s, ", schema->name);
810 else
811 fprintf(output, "no name, ");
812 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +0000813 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000814 else
815 fprintf(output, "no target namespace");
816 fprintf(output, "\n");
817 if (schema->annot != NULL)
818 xmlSchemaAnnotDump(output, schema->annot);
819
820 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
821 output);
822 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000823 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +0000824}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000825#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +0000826
827/************************************************************************
828 * *
829 * Parsing functions *
830 * *
831 ************************************************************************/
832
833/**
834 * xmlSchemaGetType:
835 * @schema: the schemas context
836 * @name: the type name
837 * @ns: the type namespace
838 *
839 * Lookup a type in the schemas or the predefined types
840 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000841 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +0000842 */
843static xmlSchemaTypePtr
844xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000845 const xmlChar * namespace)
846{
Daniel Veillard4255d502002-04-16 15:50:10 +0000847 xmlSchemaTypePtr ret;
848
849 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000850 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000851 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000852 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
853 if (ret != NULL)
854 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +0000855 }
856 ret = xmlSchemaGetPredefinedType(name, namespace);
857#ifdef DEBUG
858 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000859 if (namespace == NULL)
860 fprintf(stderr, "Unable to lookup type %s", name);
861 else
862 fprintf(stderr, "Unable to lookup type %s:%s", name,
863 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000864 }
865#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000866 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +0000867}
868
869/************************************************************************
870 * *
871 * Parsing functions *
872 * *
873 ************************************************************************/
874
875#define IS_BLANK_NODE(n) \
876 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
877
878/**
879 * xmlSchemaIsBlank:
880 * @str: a string
881 *
882 * Check if a string is ignorable
883 *
884 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
885 */
886static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000887xmlSchemaIsBlank(xmlChar * str)
888{
Daniel Veillard4255d502002-04-16 15:50:10 +0000889 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000890 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +0000891 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +0000892 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000893 return (0);
894 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +0000895 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000896 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +0000897}
898
899/**
900 * xmlSchemaAddNotation:
901 * @ctxt: a schema validation context
902 * @schema: the schema being built
903 * @name: the item name
904 *
905 * Add an XML schema Attrribute declaration
906 * *WARNING* this interface is highly subject to change
907 *
908 * Returns the new struture or NULL in case of error
909 */
910static xmlSchemaNotationPtr
911xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000912 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +0000913{
914 xmlSchemaNotationPtr ret = NULL;
915 int val;
916
917 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
918 return (NULL);
919
920 if (schema->notaDecl == NULL)
921 schema->notaDecl = xmlHashCreate(10);
922 if (schema->notaDecl == NULL)
923 return (NULL);
924
925 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
926 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000927 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000928 return (NULL);
929 }
930 memset(ret, 0, sizeof(xmlSchemaNotation));
931 ret->name = xmlStrdup(name);
932 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
933 ret);
934 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000935 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
936 XML_SCHEMAP_REDEFINED_NOTATION,
937 "Notation %s already defined\n",
938 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000939 xmlFree((char *) ret->name);
940 xmlFree(ret);
941 return (NULL);
942 }
943 return (ret);
944}
945
946
947/**
948 * xmlSchemaAddAttribute:
949 * @ctxt: a schema validation context
950 * @schema: the schema being built
951 * @name: the item name
952 * @container: the container's name
953 *
954 * Add an XML schema Attrribute declaration
955 * *WARNING* this interface is highly subject to change
956 *
957 * Returns the new struture or NULL in case of error
958 */
959static xmlSchemaAttributePtr
960xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
961 const xmlChar * name)
962{
963 xmlSchemaAttributePtr ret = NULL;
964 int val;
965
966 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
967 return (NULL);
968
969 if (schema->attrDecl == NULL)
970 schema->attrDecl = xmlHashCreate(10);
971 if (schema->attrDecl == NULL)
972 return (NULL);
973
974 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
975 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000976 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000977 return (NULL);
978 }
979 memset(ret, 0, sizeof(xmlSchemaAttribute));
980 ret->name = xmlStrdup(name);
981 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000982 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +0000983 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000984 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
985 XML_SCHEMAP_REDEFINED_ATTR,
986 "Attribute %s already defined\n",
987 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000988 xmlFree((char *) ret->name);
989 xmlFree(ret);
990 return (NULL);
991 }
992 return (ret);
993}
994
995/**
996 * xmlSchemaAddAttributeGroup:
997 * @ctxt: a schema validation context
998 * @schema: the schema being built
999 * @name: the item name
1000 *
1001 * Add an XML schema Attrribute Group declaration
1002 *
1003 * Returns the new struture or NULL in case of error
1004 */
1005static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001006xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1007 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001008{
1009 xmlSchemaAttributeGroupPtr ret = NULL;
1010 int val;
1011
1012 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1013 return (NULL);
1014
1015 if (schema->attrgrpDecl == NULL)
1016 schema->attrgrpDecl = xmlHashCreate(10);
1017 if (schema->attrgrpDecl == NULL)
1018 return (NULL);
1019
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001020 ret =
1021 (xmlSchemaAttributeGroupPtr)
1022 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001023 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001024 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001025 return (NULL);
1026 }
1027 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
1028 ret->name = xmlStrdup(name);
1029 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001030 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001031 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001032 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1033 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1034 "Attribute group %s already defined\n",
1035 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001036 xmlFree((char *) ret->name);
1037 xmlFree(ret);
1038 return (NULL);
1039 }
1040 return (ret);
1041}
1042
1043/**
1044 * xmlSchemaAddElement:
1045 * @ctxt: a schema validation context
1046 * @schema: the schema being built
1047 * @name: the type name
1048 * @namespace: the type namespace
1049 *
1050 * Add an XML schema Element declaration
1051 * *WARNING* this interface is highly subject to change
1052 *
1053 * Returns the new struture or NULL in case of error
1054 */
1055static xmlSchemaElementPtr
1056xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1057 const xmlChar * name, const xmlChar * namespace)
1058{
1059 xmlSchemaElementPtr ret = NULL;
1060 int val;
1061
1062 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1063 return (NULL);
1064
1065 if (schema->elemDecl == NULL)
1066 schema->elemDecl = xmlHashCreate(10);
1067 if (schema->elemDecl == NULL)
1068 return (NULL);
1069
1070 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1071 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001072 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001073 return (NULL);
1074 }
1075 memset(ret, 0, sizeof(xmlSchemaElement));
1076 ret->name = xmlStrdup(name);
1077 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001078 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001079 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001080 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001081
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001082 snprintf(buf, 99, "privatieelem%d", ctxt->counter++ + 1);
1083 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1084 namespace, ret);
1085 if (val != 0) {
1086 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1087 XML_SCHEMAP_REDEFINED_ELEMENT,
1088 "Element %s already defined\n",
1089 name, NULL);
1090 xmlFree((char *) ret->name);
1091 xmlFree(ret);
1092 return (NULL);
1093 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001094 }
1095 return (ret);
1096}
1097
1098/**
1099 * xmlSchemaAddType:
1100 * @ctxt: a schema validation context
1101 * @schema: the schema being built
1102 * @name: the item name
1103 *
1104 * Add an XML schema Simple Type definition
1105 * *WARNING* this interface is highly subject to change
1106 *
1107 * Returns the new struture or NULL in case of error
1108 */
1109static xmlSchemaTypePtr
1110xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1111 const xmlChar * name)
1112{
1113 xmlSchemaTypePtr ret = NULL;
1114 int val;
1115
1116 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1117 return (NULL);
1118
1119 if (schema->typeDecl == NULL)
1120 schema->typeDecl = xmlHashCreate(10);
1121 if (schema->typeDecl == NULL)
1122 return (NULL);
1123
1124 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1125 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001126 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001127 return (NULL);
1128 }
1129 memset(ret, 0, sizeof(xmlSchemaType));
1130 ret->name = xmlStrdup(name);
1131 val = xmlHashAddEntry2(schema->typeDecl, name, schema->targetNamespace,
1132 ret);
1133 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001134 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1135 XML_SCHEMAP_REDEFINED_TYPE,
1136 "Type %s already defined\n",
1137 name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001138 xmlFree((char *) ret->name);
1139 xmlFree(ret);
1140 return (NULL);
1141 }
1142 ret->minOccurs = 1;
1143 ret->maxOccurs = 1;
1144
1145 return (ret);
1146}
1147
1148/**
1149 * xmlSchemaAddGroup:
1150 * @ctxt: a schema validation context
1151 * @schema: the schema being built
1152 * @name: the group name
1153 *
1154 * Add an XML schema Group definition
1155 *
1156 * Returns the new struture or NULL in case of error
1157 */
1158static xmlSchemaTypePtr
1159xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001160 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001161{
1162 xmlSchemaTypePtr ret = NULL;
1163 int val;
1164
1165 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1166 return (NULL);
1167
1168 if (schema->groupDecl == NULL)
1169 schema->groupDecl = xmlHashCreate(10);
1170 if (schema->groupDecl == NULL)
1171 return (NULL);
1172
1173 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1174 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001175 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001176 return (NULL);
1177 }
1178 memset(ret, 0, sizeof(xmlSchemaType));
1179 ret->name = xmlStrdup(name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001180 val =
1181 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1182 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001183 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001184 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1185 XML_SCHEMAP_REDEFINED_GROUP,
1186 "Group %s already defined\n",
1187 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001188 xmlFree((char *) ret->name);
1189 xmlFree(ret);
1190 return (NULL);
1191 }
1192 ret->minOccurs = 1;
1193 ret->maxOccurs = 1;
1194
1195 return (ret);
1196}
1197
1198/************************************************************************
1199 * *
1200 * Utilities for parsing *
1201 * *
1202 ************************************************************************/
1203
1204/**
1205 * xmlGetQNameProp:
1206 * @ctxt: a schema validation context
1207 * @node: a subtree containing XML Schema informations
1208 * @name: the attribute name
1209 * @namespace: the result namespace if any
1210 *
1211 * Extract a QName Attribute value
1212 *
1213 * Returns the NCName or NULL if not found, and also update @namespace
1214 * with the namespace URI
1215 */
1216static xmlChar *
1217xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001218 const char *name, xmlChar ** namespace)
1219{
Daniel Veillard4255d502002-04-16 15:50:10 +00001220 xmlChar *val, *ret, *prefix;
1221 xmlNsPtr ns;
1222
1223
1224 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001225 *namespace = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00001226 val = xmlGetProp(node, (const xmlChar *) name);
1227 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001228 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001229
1230 ret = xmlSplitQName2(val, &prefix);
1231 if (ret == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001232 return (val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001233 xmlFree(val);
1234
1235 ns = xmlSearchNs(node->doc, node, prefix);
1236 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001237 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1238 "Attribute %s: the QName prefix %s is undefined\n",
1239 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001240 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001241 *namespace = xmlStrdup(ns->href);
Daniel Veillard4255d502002-04-16 15:50:10 +00001242 }
1243 xmlFree(prefix);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001244 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001245}
1246
1247/**
1248 * xmlGetMaxOccurs:
1249 * @ctxt: a schema validation context
1250 * @node: a subtree containing XML Schema informations
1251 *
1252 * Get the maxOccurs property
1253 *
1254 * Returns the default if not found, or the value
1255 */
1256static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001257xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1258{
Daniel Veillard4255d502002-04-16 15:50:10 +00001259 xmlChar *val, *cur;
1260 int ret = 0;
1261
1262 val = xmlGetProp(node, (const xmlChar *) "maxOccurs");
1263 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001264 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001265
1266 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001267 xmlFree(val);
1268 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001269 }
1270
1271 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001272 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001273 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001274 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001275 ret = ret * 10 + (*cur - '0');
1276 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001277 }
William M. Brack76e95df2003-10-18 16:20:14 +00001278 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001279 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001280 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001281 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1282 "invalid value for maxOccurs: %s\n", val, NULL);
1283 xmlFree(val);
1284 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001285 }
1286 xmlFree(val);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001287 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001288}
1289
1290/**
1291 * xmlGetMinOccurs:
1292 * @ctxt: a schema validation context
1293 * @node: a subtree containing XML Schema informations
1294 *
1295 * Get the minOccurs property
1296 *
1297 * Returns the default if not found, or the value
1298 */
1299static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001300xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1301{
Daniel Veillard4255d502002-04-16 15:50:10 +00001302 xmlChar *val, *cur;
1303 int ret = 0;
1304
1305 val = xmlGetProp(node, (const xmlChar *) "minOccurs");
1306 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001307 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001308
1309 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001310 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001311 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001312 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001313 ret = ret * 10 + (*cur - '0');
1314 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001315 }
William M. Brack76e95df2003-10-18 16:20:14 +00001316 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001317 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001318 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001319 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1320 "invalid value for minOccurs: %s\n", val, NULL);
1321 xmlFree(val);
1322 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001323 }
1324 xmlFree(val);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001325 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001326}
1327
1328/**
1329 * xmlGetBooleanProp:
1330 * @ctxt: a schema validation context
1331 * @node: a subtree containing XML Schema informations
1332 * @name: the attribute name
1333 * @def: the default value
1334 *
1335 * Get is a bolean property is set
1336 *
1337 * Returns the default if not found, 0 if found to be false,
1338 * 1 if found to be true
1339 */
1340static int
1341xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001342 const char *name, int def)
1343{
Daniel Veillard4255d502002-04-16 15:50:10 +00001344 xmlChar *val;
1345
1346 val = xmlGetProp(node, (const xmlChar *) name);
1347 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001348 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001349
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001350 if (xmlStrEqual(val, BAD_CAST "true"))
1351 def = 1;
1352 else if (xmlStrEqual(val, BAD_CAST "false"))
1353 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001354 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001355 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1356 "Attribute %s: the value %s is not boolean\n",
1357 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001358 }
1359 xmlFree(val);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001360 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001361}
1362
1363/************************************************************************
1364 * *
1365 * Shema extraction from an Infoset *
1366 * *
1367 ************************************************************************/
1368static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1369 ctxt, xmlSchemaPtr schema,
1370 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001371static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1372 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001373 xmlSchemaPtr schema,
1374 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001375static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1376 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001377 xmlSchemaPtr schema,
1378 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001379 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001380static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1381 xmlSchemaPtr schema,
1382 xmlNodePtr node);
1383static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1384 xmlSchemaPtr schema,
1385 xmlNodePtr node);
1386static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1387 ctxt,
1388 xmlSchemaPtr schema,
1389 xmlNodePtr node);
1390static xmlSchemaAttributeGroupPtr
1391xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1392 xmlSchemaPtr schema, xmlNodePtr node);
1393static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1394 xmlSchemaPtr schema,
1395 xmlNodePtr node);
1396static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1397 xmlSchemaPtr schema,
1398 xmlNodePtr node);
1399static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001400xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1401 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001402
1403/**
1404 * xmlSchemaParseAttrDecls:
1405 * @ctxt: a schema validation context
1406 * @schema: the schema being built
1407 * @node: a subtree containing XML Schema informations
1408 * @type: the hosting type
1409 *
1410 * parse a XML schema attrDecls declaration corresponding to
1411 * <!ENTITY % attrDecls
1412 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1413 */
1414static xmlNodePtr
1415xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1416 xmlNodePtr child, xmlSchemaTypePtr type)
1417{
1418 xmlSchemaAttributePtr lastattr, attr;
1419
1420 lastattr = NULL;
1421 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001422 (IS_SCHEMA(child, "attributeGroup"))) {
1423 attr = NULL;
1424 if (IS_SCHEMA(child, "attribute")) {
1425 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1426 } else if (IS_SCHEMA(child, "attributeGroup")) {
1427 attr = (xmlSchemaAttributePtr)
1428 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1429 }
1430 if (attr != NULL) {
1431 if (lastattr == NULL) {
1432 type->attributes = attr;
1433 lastattr = attr;
1434 } else {
1435 lastattr->next = attr;
1436 lastattr = attr;
1437 }
1438 }
1439 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001440 }
1441 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001442 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1443 if (attr != NULL) {
1444 if (lastattr == NULL) {
1445 type->attributes = attr;
1446 lastattr = attr;
1447 } else {
1448 lastattr->next = attr;
1449 lastattr = attr;
1450 }
1451 }
1452 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001453 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001454 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001455}
1456
1457/**
1458 * xmlSchemaParseAnnotation:
1459 * @ctxt: a schema validation context
1460 * @schema: the schema being built
1461 * @node: a subtree containing XML Schema informations
1462 *
1463 * parse a XML schema Attrribute declaration
1464 * *WARNING* this interface is highly subject to change
1465 *
1466 * Returns -1 in case of error, 0 if the declaration is inproper and
1467 * 1 in case of success.
1468 */
1469static xmlSchemaAnnotPtr
1470xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1471 xmlNodePtr node)
1472{
1473 xmlSchemaAnnotPtr ret;
1474
1475 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1476 return (NULL);
1477 ret = xmlSchemaNewAnnot(ctxt, node);
1478
1479 return (ret);
1480}
1481
1482/**
1483 * xmlSchemaParseFacet:
1484 * @ctxt: a schema validation context
1485 * @schema: the schema being built
1486 * @node: a subtree containing XML Schema informations
1487 *
1488 * parse a XML schema Facet declaration
1489 * *WARNING* this interface is highly subject to change
1490 *
1491 * Returns the new type structure or NULL in case of error
1492 */
1493static xmlSchemaFacetPtr
1494xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001495 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001496{
1497 xmlSchemaFacetPtr facet;
1498 xmlNodePtr child = NULL;
1499 xmlChar *value;
1500
1501 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1502 return (NULL);
1503
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001504 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001505 if (facet == NULL) {
1506 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1507 return (NULL);
1508 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001509 facet->node = node;
1510 value = xmlGetProp(node, (const xmlChar *) "value");
1511 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001512 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1513 "Facet %s has no value\n", node->name, NULL);
1514 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001515 return (NULL);
1516 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001517 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001518 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001519 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001520 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001521 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001522 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001523 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001524 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001525 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001526 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001527 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001528 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001529 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001530 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001531 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001532 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001533 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001534 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001535 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001536 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001537 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001538 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1539 } else if (IS_SCHEMA(node, "minLength")) {
1540 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1541 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001542 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1543 "Unknown facet type %s\n", node->name, NULL);
1544 xmlSchemaFreeFacet(facet);
1545 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001546 }
1547 facet->id = xmlGetProp(node, (const xmlChar *) "id");
1548 facet->value = value;
1549 child = node->children;
1550
1551 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001552 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1553 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001554 }
1555 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001556 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1557 "Facet %s has unexpected child content\n",
1558 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001559 }
1560 return (facet);
1561}
1562
1563/**
1564 * xmlSchemaParseAny:
1565 * @ctxt: a schema validation context
1566 * @schema: the schema being built
1567 * @node: a subtree containing XML Schema informations
1568 *
1569 * parse a XML schema Any declaration
1570 * *WARNING* this interface is highly subject to change
1571 *
1572 * Returns the new type structure or NULL in case of error
1573 */
1574static xmlSchemaTypePtr
1575xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1576 xmlNodePtr node)
1577{
1578 xmlSchemaTypePtr type;
1579 xmlNodePtr child = NULL;
1580 xmlChar name[30];
1581
1582 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1583 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001584 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001585 type = xmlSchemaAddType(ctxt, schema, name);
1586 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001587 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001588 type->node = node;
1589 type->type = XML_SCHEMA_TYPE_ANY;
1590 child = node->children;
1591 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1592 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1593
1594 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001595 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1596 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001597 }
1598 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001599 xmlSchemaPErr2(ctxt, node, child,
1600 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1601 "Sequence %s has unexpected content\n", type->name,
1602 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001603 }
1604
1605 return (type);
1606}
1607
1608/**
1609 * xmlSchemaParseNotation:
1610 * @ctxt: a schema validation context
1611 * @schema: the schema being built
1612 * @node: a subtree containing XML Schema informations
1613 *
1614 * parse a XML schema Notation declaration
1615 *
1616 * Returns the new structure or NULL in case of error
1617 */
1618static xmlSchemaNotationPtr
1619xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001620 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001621{
1622 xmlChar *name;
1623 xmlSchemaNotationPtr ret;
1624 xmlNodePtr child = NULL;
1625
1626 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1627 return (NULL);
1628 name = xmlGetProp(node, (const xmlChar *) "name");
1629 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001630 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1631 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001632 return (NULL);
1633 }
1634 ret = xmlSchemaAddNotation(ctxt, schema, name);
1635 if (ret == NULL) {
1636 xmlFree(name);
1637 return (NULL);
1638 }
1639 child = node->children;
1640 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001641 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1642 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001643 }
1644 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001645 xmlSchemaPErr2(ctxt, node, child,
1646 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1647 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001648 }
1649
1650 return (ret);
1651}
1652
1653/**
1654 * xmlSchemaParseAnyAttribute:
1655 * @ctxt: a schema validation context
1656 * @schema: the schema being built
1657 * @node: a subtree containing XML Schema informations
1658 *
1659 * parse a XML schema AnyAttrribute declaration
1660 * *WARNING* this interface is highly subject to change
1661 *
1662 * Returns an attribute def structure or NULL
1663 */
1664static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001665xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1666 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001667{
1668 xmlChar *processContents;
1669 xmlSchemaAttributePtr ret;
1670 xmlNodePtr child = NULL;
1671 char name[100];
1672
1673 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1674 return (NULL);
1675
1676 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001677 ret = xmlSchemaAddAttribute(ctxt, schema, (xmlChar *) name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001678 if (ret == NULL) {
1679 return (NULL);
1680 }
1681 ret->id = xmlGetProp(node, (const xmlChar *) "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001682 processContents =
1683 xmlGetProp(node, (const xmlChar *) "processContents");
1684 if ((processContents == NULL)
1685 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1686 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1687 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1688 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1689 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1690 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001691 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001692 xmlSchemaPErr2(ctxt, node, child,
1693 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
1694 "anyAttribute has unexpected content for processContents: %s\n",
1695 processContents, NULL);
1696 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001697 }
1698 if (processContents != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001699 xmlFree(processContents);
Daniel Veillard4255d502002-04-16 15:50:10 +00001700
1701 child = node->children;
1702 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001703 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1704 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001705 }
1706 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001707 xmlSchemaPErr2(ctxt, node, child,
1708 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
1709 "anyAttribute %s has unexpected content\n",
1710 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001711 }
1712
1713 return (ret);
1714}
1715
1716
1717/**
1718 * xmlSchemaParseAttribute:
1719 * @ctxt: a schema validation context
1720 * @schema: the schema being built
1721 * @node: a subtree containing XML Schema informations
1722 *
1723 * parse a XML schema Attrribute declaration
1724 * *WARNING* this interface is highly subject to change
1725 *
1726 * Returns -1 in case of error, 0 if the declaration is inproper and
1727 * 1 in case of success.
1728 */
1729static xmlSchemaAttributePtr
1730xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1731 xmlNodePtr node)
1732{
1733 xmlChar *name, *refNs = NULL, *ref = NULL;
1734 xmlSchemaAttributePtr ret;
1735 xmlNodePtr child = NULL;
1736
1737 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1738 return (NULL);
1739 name = xmlGetProp(node, (const xmlChar *) "name");
1740 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001741 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001742
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001743 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1744 if (ref == NULL) {
1745 xmlSchemaPErr2(ctxt, node, child,
1746 XML_SCHEMAP_ATTR_NONAME_NOREF,
1747 "Attribute has no name nor ref\n", NULL, NULL);
1748 return (NULL);
1749 }
1750 snprintf(buf, 99, "anonattr%d", ctxt->counter++ + 1);
1751 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00001752 }
1753 ret = xmlSchemaAddAttribute(ctxt, schema, name);
1754 if (ret == NULL) {
1755 xmlFree(name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001756 if (ref != NULL)
1757 xmlFree(ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001758 return (NULL);
1759 }
1760 xmlFree(name);
1761 ret->ref = ref;
1762 ret->refNs = refNs;
1763 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00001764 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001765 child = node->children;
1766 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001767 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1768 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001769 }
1770 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001771 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1772 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001773 }
1774 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001775 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
1776 "attribute %s has unexpected content\n", name,
1777 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001778 }
1779
1780 return (ret);
1781}
1782
1783/**
1784 * xmlSchemaParseAttributeGroup:
1785 * @ctxt: a schema validation context
1786 * @schema: the schema being built
1787 * @node: a subtree containing XML Schema informations
1788 *
1789 * parse a XML schema Attribute Group declaration
1790 * *WARNING* this interface is highly subject to change
1791 *
1792 * Returns the attribute group or NULL in case of error.
1793 */
1794static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001795xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1796 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001797{
1798 xmlChar *name, *refNs = NULL, *ref = NULL;
1799 xmlSchemaAttributeGroupPtr ret;
1800 xmlSchemaAttributePtr last = NULL, attr;
1801 xmlNodePtr child = NULL;
1802 xmlChar *oldcontainer;
1803
1804 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1805 return (NULL);
1806 oldcontainer = ctxt->container;
1807 name = xmlGetProp(node, (const xmlChar *) "name");
1808 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001809 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001810
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001811 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1812 if (ref == NULL) {
1813 xmlSchemaPErr2(ctxt, node, child,
1814 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
1815 "AttributeGroup has no name nor ref\n", NULL,
1816 NULL);
1817 return (NULL);
1818 }
1819 snprintf(buf, 99, "anonattrgroup%d", ctxt->counter++ + 1);
1820 name = xmlStrdup((xmlChar *) buf);
1821 if (name == NULL) {
1822 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
1823 return (NULL);
1824 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001825 }
1826 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
1827 if (ret == NULL) {
1828 xmlFree(name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001829 if (ref != NULL)
1830 xmlFree(ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001831 return (NULL);
1832 }
1833 ret->ref = ref;
1834 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00001835 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00001836 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001837 child = node->children;
1838 ctxt->container = name;
1839 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001840 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1841 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001842 }
1843 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001844 (IS_SCHEMA(child, "attributeGroup"))) {
1845 attr = NULL;
1846 if (IS_SCHEMA(child, "attribute")) {
1847 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1848 } else if (IS_SCHEMA(child, "attributeGroup")) {
1849 attr = (xmlSchemaAttributePtr)
1850 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1851 }
1852 if (attr != NULL) {
1853 if (last == NULL) {
1854 ret->attributes = attr;
1855 last = attr;
1856 } else {
1857 last->next = attr;
1858 last = attr;
1859 }
1860 }
1861 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001862 }
1863 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001864 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001865 }
1866 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001867 xmlSchemaPErr2(ctxt, node, child,
1868 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
1869 "attribute group %s has unexpected content\n", name,
1870 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001871 }
1872
1873 ctxt->container = oldcontainer;
Daniel Veillard91a13252003-03-27 23:44:43 +00001874 xmlFree(name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001875 return (ret);
1876}
1877
1878/**
1879 * xmlSchemaParseElement:
1880 * @ctxt: a schema validation context
1881 * @schema: the schema being built
1882 * @node: a subtree containing XML Schema informations
1883 *
1884 * parse a XML schema Element declaration
1885 * *WARNING* this interface is highly subject to change
1886 *
1887 * Returns -1 in case of error, 0 if the declaration is inproper and
1888 * 1 in case of success.
1889 */
1890static xmlSchemaElementPtr
1891xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1892 xmlNodePtr node, int toplevel)
1893{
1894 xmlChar *name, *refNs = NULL, *ref = NULL, *namespace, *fixed;
1895 xmlSchemaElementPtr ret;
1896 xmlNodePtr child = NULL;
1897 xmlChar *oldcontainer;
1898
1899 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1900 return (NULL);
1901 oldcontainer = ctxt->container;
1902 name = xmlGetProp(node, (const xmlChar *) "name");
1903 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001904 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001905
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001906 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1907 if (ref == NULL) {
1908 xmlSchemaPErr2(ctxt, node, child,
1909 XML_SCHEMAP_ELEM_NONAME_NOREF,
1910 "Element has no name nor ref\n", NULL, NULL);
1911 return (NULL);
1912 }
1913 snprintf(buf, 99, "anonelem%d", ctxt->counter++ + 1);
1914 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00001915 }
1916 namespace = xmlGetProp(node, (const xmlChar *) "targetNamespace");
1917 if (namespace == NULL)
1918 ret =
1919 xmlSchemaAddElement(ctxt, schema, name,
1920 schema->targetNamespace);
1921 else
1922 ret = xmlSchemaAddElement(ctxt, schema, name, namespace);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001923 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001924 if (namespace != NULL)
1925 xmlFree(namespace);
1926 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001927 xmlFree(name);
1928 if (ref != NULL)
1929 xmlFree(ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001930 return (NULL);
1931 }
1932 ret->type = XML_SCHEMA_TYPE_ELEMENT;
1933 ret->ref = ref;
1934 ret->refNs = refNs;
1935 if (ref != NULL)
1936 ret->flags |= XML_SCHEMAS_ELEM_REF;
1937 if (toplevel)
1938 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
1939 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
1940 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1941 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
1942 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1943 ctxt->container = name;
1944
1945 ret->id = xmlGetProp(node, BAD_CAST "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001946 ret->namedType =
1947 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
1948 ret->substGroup =
1949 xmlGetQNameProp(ctxt, node, "substitutionGroup",
1950 &(ret->substGroupNs));
Daniel Veillard4255d502002-04-16 15:50:10 +00001951 fixed = xmlGetProp(node, BAD_CAST "fixed");
1952 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
1953 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001954
Daniel Veillard4255d502002-04-16 15:50:10 +00001955 ret->value = xmlGetProp(node, BAD_CAST "default");
1956 if ((ret->value != NULL) && (fixed != NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001957 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
1958 "Element %s has both default and fixed\n",
1959 ret->name, NULL);
1960 xmlFree(fixed);
Daniel Veillard4255d502002-04-16 15:50:10 +00001961 } else if (fixed != NULL) {
1962 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001963 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00001964 }
1965
1966 child = node->children;
1967 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001968 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1969 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001970 }
1971 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001972 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001973 child = child->next;
1974 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001975 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001976 child = child->next;
1977 }
1978 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001979 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
1980 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001981 }
1982 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001983 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
1984 "element %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001985 }
1986
1987 ctxt->container = oldcontainer;
1988 xmlFree(name);
1989 return (ret);
1990}
1991
1992/**
1993 * xmlSchemaParseUnion:
1994 * @ctxt: a schema validation context
1995 * @schema: the schema being built
1996 * @node: a subtree containing XML Schema informations
1997 *
1998 * parse a XML schema Union definition
1999 * *WARNING* this interface is highly subject to change
2000 *
2001 * Returns -1 in case of error, 0 if the declaration is inproper and
2002 * 1 in case of success.
2003 */
2004static xmlSchemaTypePtr
2005xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002006 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002007{
2008 xmlSchemaTypePtr type, subtype, last = NULL;
2009 xmlNodePtr child = NULL;
2010 xmlChar name[30];
2011
2012 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2013 return (NULL);
2014
2015
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002016 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002017 type = xmlSchemaAddType(ctxt, schema, name);
2018 if (type == NULL)
2019 return (NULL);
2020 type->node = node;
2021 type->type = XML_SCHEMA_TYPE_LIST;
2022 type->id = xmlGetProp(node, BAD_CAST "id");
2023 type->ref = xmlGetProp(node, BAD_CAST "memberTypes");
2024
2025 child = node->children;
2026 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002027 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2028 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002029 }
2030 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002031 subtype = (xmlSchemaTypePtr)
2032 xmlSchemaParseSimpleType(ctxt, schema, child);
2033 if (subtype != NULL) {
2034 if (last == NULL) {
2035 type->subtypes = subtype;
2036 last = subtype;
2037 } else {
2038 last->next = subtype;
2039 last = subtype;
2040 }
2041 last->next = NULL;
2042 }
2043 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002044 }
2045 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002046 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2047 "Union %s has unexpected content\n", type->name,
2048 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002049 }
2050 return (type);
2051}
2052
2053/**
2054 * xmlSchemaParseList:
2055 * @ctxt: a schema validation context
2056 * @schema: the schema being built
2057 * @node: a subtree containing XML Schema informations
2058 *
2059 * parse a XML schema List definition
2060 * *WARNING* this interface is highly subject to change
2061 *
2062 * Returns -1 in case of error, 0 if the declaration is inproper and
2063 * 1 in case of success.
2064 */
2065static xmlSchemaTypePtr
2066xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002067 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002068{
2069 xmlSchemaTypePtr type, subtype;
2070 xmlNodePtr child = NULL;
2071 xmlChar name[30];
2072
2073 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2074 return (NULL);
2075
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002076 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002077 type = xmlSchemaAddType(ctxt, schema, name);
2078 if (type == NULL)
2079 return (NULL);
2080 type->node = node;
2081 type->type = XML_SCHEMA_TYPE_LIST;
2082 type->id = xmlGetProp(node, BAD_CAST "id");
2083 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2084
2085 child = node->children;
2086 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002087 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2088 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002089 }
2090 subtype = NULL;
2091 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002092 subtype = (xmlSchemaTypePtr)
2093 xmlSchemaParseSimpleType(ctxt, schema, child);
2094 child = child->next;
2095 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002096 }
2097 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002098 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2099 "List %s has unexpected content\n", type->name,
2100 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002101 }
2102 return (type);
2103}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002104
Daniel Veillard4255d502002-04-16 15:50:10 +00002105/**
2106 * xmlSchemaParseSimpleType:
2107 * @ctxt: a schema validation context
2108 * @schema: the schema being built
2109 * @node: a subtree containing XML Schema informations
2110 *
2111 * parse a XML schema Simple Type definition
2112 * *WARNING* this interface is highly subject to change
2113 *
2114 * Returns -1 in case of error, 0 if the declaration is inproper and
2115 * 1 in case of success.
2116 */
2117static xmlSchemaTypePtr
2118xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2119 xmlNodePtr node)
2120{
2121 xmlSchemaTypePtr type, subtype;
2122 xmlNodePtr child = NULL;
2123 xmlChar *name;
2124
2125 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2126 return (NULL);
2127
2128
2129 name = xmlGetProp(node, (const xmlChar *) "name");
2130 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002131 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002132
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002133 snprintf(buf, 99, "simpletype%d", ctxt->counter++ + 1);
2134 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00002135 }
2136 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002137 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_SIMPLETYPE_NONAME,
2138 "simpleType has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002139 return (NULL);
2140 }
2141 type = xmlSchemaAddType(ctxt, schema, name);
2142 xmlFree(name);
2143 if (type == NULL)
2144 return (NULL);
2145 type->node = node;
2146 type->type = XML_SCHEMA_TYPE_SIMPLE;
2147 type->id = xmlGetProp(node, BAD_CAST "id");
2148
2149 child = node->children;
2150 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002151 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2152 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002153 }
2154 subtype = NULL;
2155 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002156 subtype = (xmlSchemaTypePtr)
2157 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2158 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002159 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002160 subtype = (xmlSchemaTypePtr)
2161 xmlSchemaParseList(ctxt, schema, child);
2162 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002163 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002164 subtype = (xmlSchemaTypePtr)
2165 xmlSchemaParseUnion(ctxt, schema, child);
2166 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002167 }
2168 type->subtypes = subtype;
2169 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002170 xmlSchemaPErr2(ctxt, node, child,
2171 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2172 "SimpleType %s has unexpected content\n",
2173 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002174 }
2175
2176 return (type);
2177}
2178
2179
2180/**
2181 * xmlSchemaParseGroup:
2182 * @ctxt: a schema validation context
2183 * @schema: the schema being built
2184 * @node: a subtree containing XML Schema informations
2185 *
2186 * parse a XML schema Group definition
2187 * *WARNING* this interface is highly subject to change
2188 *
2189 * Returns -1 in case of error, 0 if the declaration is inproper and
2190 * 1 in case of success.
2191 */
2192static xmlSchemaTypePtr
2193xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002194 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002195{
2196 xmlSchemaTypePtr type, subtype;
2197 xmlNodePtr child = NULL;
2198 xmlChar *name, *ref = NULL, *refNs = NULL;
2199
2200 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2201 return (NULL);
2202
2203
2204 name = xmlGetProp(node, (const xmlChar *) "name");
2205 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002206 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002207
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002208 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2209 if (ref == NULL) {
2210 xmlSchemaPErr2(ctxt, node, child,
2211 XML_SCHEMAP_GROUP_NONAME_NOREF,
2212 "Group has no name nor ref\n", NULL, NULL);
2213 return (NULL);
2214 }
2215 snprintf(buf, 99, "anongroup%d", ctxt->counter++ + 1);
2216 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00002217 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002218 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002219 if (type == NULL)
2220 return (NULL);
2221 type->node = node;
2222 type->type = XML_SCHEMA_TYPE_GROUP;
2223 type->id = xmlGetProp(node, BAD_CAST "id");
2224 type->ref = ref;
2225 type->refNs = refNs;
2226 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2227 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2228
2229 child = node->children;
2230 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002231 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2232 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002233 }
2234 subtype = NULL;
2235 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002236 subtype = (xmlSchemaTypePtr)
2237 xmlSchemaParseAll(ctxt, schema, child);
2238 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002239 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002240 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2241 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002242 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002243 subtype = (xmlSchemaTypePtr)
2244 xmlSchemaParseSequence(ctxt, schema, child);
2245 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002246 }
2247 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002248 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002249 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002250 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2251 "Group %s has unexpected content\n", type->name,
2252 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002253 }
2254
2255 return (type);
2256}
2257
2258/**
2259 * xmlSchemaParseAll:
2260 * @ctxt: a schema validation context
2261 * @schema: the schema being built
2262 * @node: a subtree containing XML Schema informations
2263 *
2264 * parse a XML schema All definition
2265 * *WARNING* this interface is highly subject to change
2266 *
2267 * Returns -1 in case of error, 0 if the declaration is inproper and
2268 * 1 in case of success.
2269 */
2270static xmlSchemaTypePtr
2271xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002272 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002273{
2274 xmlSchemaTypePtr type, subtype, last = NULL;
2275 xmlNodePtr child = NULL;
2276 xmlChar name[30];
2277
2278 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2279 return (NULL);
2280
2281
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002282 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002283 type = xmlSchemaAddType(ctxt, schema, name);
2284 if (type == NULL)
2285 return (NULL);
2286 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002287 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002288 type->id = xmlGetProp(node, BAD_CAST "id");
2289 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2290 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2291
2292 child = node->children;
2293 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002294 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2295 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002296 }
2297 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002298 subtype = (xmlSchemaTypePtr)
2299 xmlSchemaParseElement(ctxt, schema, child, 0);
2300 if (subtype != NULL) {
2301 if (last == NULL) {
2302 type->subtypes = subtype;
2303 last = subtype;
2304 } else {
2305 last->next = subtype;
2306 last = subtype;
2307 }
2308 last->next = NULL;
2309 }
2310 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002311 }
2312 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002313 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2314 "All %s has unexpected content\n", type->name,
2315 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002316 }
2317
2318 return (type);
2319}
2320
2321/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002322 * xmlSchemaParseImport:
2323 * @ctxt: a schema validation context
2324 * @schema: the schema being built
2325 * @node: a subtree containing XML Schema informations
2326 *
2327 * parse a XML schema Import definition
2328 * *WARNING* this interface is highly subject to change
2329 *
2330 * Returns -1 in case of error, 0 if the declaration is inproper and
2331 * 1 in case of success.
2332 */
2333static int
2334xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002335 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002336{
2337 xmlNodePtr child = NULL;
2338 xmlChar *namespace;
2339 xmlChar *schemaLocation;
2340 xmlChar *previous;
2341 xmlURIPtr check;
2342
2343 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2344 return (-1);
2345
2346 namespace = xmlGetProp(node, BAD_CAST "namespace");
2347 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002348 check = xmlParseURI((const char *) namespace);
2349 if (check == NULL) {
2350 xmlSchemaPErr2(ctxt, node, child,
2351 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2352 "Import namespace attribute is not an URI: %s\n",
2353 namespace, NULL);
2354 xmlFree(namespace);
2355 return (-1);
2356 } else {
2357 xmlFreeURI(check);
2358 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002359 }
2360 schemaLocation = xmlGetProp(node, BAD_CAST "schemaLocation");
2361 if (schemaLocation != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002362 check = xmlParseURI((const char *) schemaLocation);
2363 if (check == NULL) {
2364 xmlSchemaPErr2(ctxt, node, child,
2365 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2366 "Import schemaLocation attribute is not an URI: %s\n",
2367 schemaLocation, NULL);
2368 if (namespace != NULL)
2369 xmlFree(namespace);
2370 xmlFree(schemaLocation);
2371 return (-1);
2372 } else {
2373 xmlFreeURI(check);
2374 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002375 }
2376 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002377 schema->schemasImports = xmlHashCreate(10);
2378 if (schema->schemasImports == NULL) {
2379 xmlSchemaPErr2(ctxt, node, child,
2380 XML_SCHEMAP_FAILED_BUILD_IMPORT,
2381 "Internal: failed to build import table\n",
2382 NULL, NULL);
2383 if (namespace != NULL)
2384 xmlFree(namespace);
2385 if (schemaLocation != NULL)
2386 xmlFree(schemaLocation);
2387 return (-1);
2388 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002389 }
2390 if (namespace == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002391 previous = xmlHashLookup(schema->schemasImports,
2392 XML_SCHEMAS_DEFAULT_NAMESPACE);
2393 if (schemaLocation != NULL) {
2394 if (previous != NULL) {
2395 if (!xmlStrEqual(schemaLocation, previous)) {
2396 xmlSchemaPErr2(ctxt, node, child,
2397 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2398 "Redefining import for default namespace with a different URI: %s\n",
2399 schemaLocation, NULL);
2400 }
2401 } else {
2402 xmlHashAddEntry(schema->schemasImports,
2403 XML_SCHEMAS_DEFAULT_NAMESPACE,
2404 schemaLocation);
2405 }
2406 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002407 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002408 previous = xmlHashLookup(schema->schemasImports, namespace);
2409 if (schemaLocation != NULL) {
2410 if (previous != NULL) {
2411 if (!xmlStrEqual(schemaLocation, previous)) {
2412 xmlSchemaPErr2(ctxt, node, child,
2413 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2414 "Redefining import for namespace %s with a different URI: %s\n",
2415 namespace, schemaLocation);
2416 }
2417 } else {
2418 xmlHashAddEntry(schema->schemasImports,
2419 namespace, schemaLocation);
2420 }
2421 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002422 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002423
2424 child = node->children;
2425 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002426 /*
2427 * the annotations here are simply discarded ...
2428 */
2429 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00002430 }
2431 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002432 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
2433 "Import has unexpected content\n", NULL, NULL);
2434 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002435 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002436 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002437}
2438
2439/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002440 * xmlSchemaParseChoice:
2441 * @ctxt: a schema validation context
2442 * @schema: the schema being built
2443 * @node: a subtree containing XML Schema informations
2444 *
2445 * parse a XML schema Choice definition
2446 * *WARNING* this interface is highly subject to change
2447 *
2448 * Returns -1 in case of error, 0 if the declaration is inproper and
2449 * 1 in case of success.
2450 */
2451static xmlSchemaTypePtr
2452xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002453 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002454{
2455 xmlSchemaTypePtr type, subtype, last = NULL;
2456 xmlNodePtr child = NULL;
2457 xmlChar name[30];
2458
2459 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2460 return (NULL);
2461
2462
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002463 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002464 type = xmlSchemaAddType(ctxt, schema, name);
2465 if (type == NULL)
2466 return (NULL);
2467 type->node = node;
2468 type->type = XML_SCHEMA_TYPE_CHOICE;
2469 type->id = xmlGetProp(node, BAD_CAST "id");
2470 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2471 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2472
2473 child = node->children;
2474 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002475 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2476 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002477 }
2478 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002479 (IS_SCHEMA(child, "group")) ||
2480 (IS_SCHEMA(child, "any")) ||
2481 (IS_SCHEMA(child, "choice")) ||
2482 (IS_SCHEMA(child, "sequence"))) {
2483 subtype = NULL;
2484 if (IS_SCHEMA(child, "element")) {
2485 subtype = (xmlSchemaTypePtr)
2486 xmlSchemaParseElement(ctxt, schema, child, 0);
2487 } else if (IS_SCHEMA(child, "group")) {
2488 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2489 } else if (IS_SCHEMA(child, "any")) {
2490 subtype = xmlSchemaParseAny(ctxt, schema, child);
2491 } else if (IS_SCHEMA(child, "sequence")) {
2492 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2493 } else if (IS_SCHEMA(child, "choice")) {
2494 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2495 }
2496 if (subtype != NULL) {
2497 if (last == NULL) {
2498 type->subtypes = subtype;
2499 last = subtype;
2500 } else {
2501 last->next = subtype;
2502 last = subtype;
2503 }
2504 last->next = NULL;
2505 }
2506 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002507 }
2508 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002509 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
2510 "Choice %s has unexpected content\n", type->name,
2511 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002512 }
2513
2514 return (type);
2515}
2516
2517/**
2518 * xmlSchemaParseSequence:
2519 * @ctxt: a schema validation context
2520 * @schema: the schema being built
2521 * @node: a subtree containing XML Schema informations
2522 *
2523 * parse a XML schema Sequence definition
2524 * *WARNING* this interface is highly subject to change
2525 *
2526 * Returns -1 in case of error, 0 if the declaration is inproper and
2527 * 1 in case of success.
2528 */
2529static xmlSchemaTypePtr
2530xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002531 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002532{
2533 xmlSchemaTypePtr type, subtype, last = NULL;
2534 xmlNodePtr child = NULL;
2535 xmlChar name[30];
2536
2537 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2538 return (NULL);
2539
2540
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002541 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002542 type = xmlSchemaAddType(ctxt, schema, name);
2543 if (type == NULL)
2544 return (NULL);
2545 type->node = node;
2546 type->type = XML_SCHEMA_TYPE_SEQUENCE;
2547 type->id = xmlGetProp(node, BAD_CAST "id");
2548 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2549 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2550
2551 child = node->children;
2552 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002553 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2554 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002555 }
2556 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002557 (IS_SCHEMA(child, "group")) ||
2558 (IS_SCHEMA(child, "any")) ||
2559 (IS_SCHEMA(child, "choice")) ||
2560 (IS_SCHEMA(child, "sequence"))) {
2561 subtype = NULL;
2562 if (IS_SCHEMA(child, "element")) {
2563 subtype = (xmlSchemaTypePtr)
2564 xmlSchemaParseElement(ctxt, schema, child, 0);
2565 } else if (IS_SCHEMA(child, "group")) {
2566 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2567 } else if (IS_SCHEMA(child, "any")) {
2568 subtype = xmlSchemaParseAny(ctxt, schema, child);
2569 } else if (IS_SCHEMA(child, "choice")) {
2570 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2571 } else if (IS_SCHEMA(child, "sequence")) {
2572 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2573 }
2574 if (subtype != NULL) {
2575 if (last == NULL) {
2576 type->subtypes = subtype;
2577 last = subtype;
2578 } else {
2579 last->next = subtype;
2580 last = subtype;
2581 }
2582 last->next = NULL;
2583 }
2584 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002585 }
2586 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002587 xmlSchemaPErr2(ctxt, node, child,
2588 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
2589 "Sequence %s has unexpected content\n", type->name,
2590 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002591 }
2592
2593 return (type);
2594}
2595
2596/**
2597 * xmlSchemaParseRestriction:
2598 * @ctxt: a schema validation context
2599 * @schema: the schema being built
2600 * @node: a subtree containing XML Schema informations
2601 * @simple: is that part of a simple type.
2602 *
2603 * parse a XML schema Restriction definition
2604 * *WARNING* this interface is highly subject to change
2605 *
2606 * Returns the type definition or NULL in case of error
2607 */
2608static xmlSchemaTypePtr
2609xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2610 xmlNodePtr node, int simple)
2611{
2612 xmlSchemaTypePtr type, subtype;
2613 xmlSchemaFacetPtr facet, lastfacet = NULL;
2614 xmlNodePtr child = NULL;
2615 xmlChar name[30];
2616 xmlChar *oldcontainer;
2617
2618 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2619 return (NULL);
2620
2621 oldcontainer = ctxt->container;
2622
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002623 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002624 type = xmlSchemaAddType(ctxt, schema, name);
2625 if (type == NULL)
2626 return (NULL);
2627 type->node = node;
2628 type->type = XML_SCHEMA_TYPE_RESTRICTION;
2629 type->id = xmlGetProp(node, BAD_CAST "id");
2630 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2631 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002632 xmlSchemaPErr2(ctxt, node, child,
2633 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
2634 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002635 }
2636 ctxt->container = name;
2637
2638 child = node->children;
2639 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002640 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2641 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002642 }
2643 subtype = NULL;
2644
2645 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002646 subtype = (xmlSchemaTypePtr)
2647 xmlSchemaParseAll(ctxt, schema, child);
2648 child = child->next;
2649 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002650 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002651 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2652 child = child->next;
2653 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002654 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002655 subtype = (xmlSchemaTypePtr)
2656 xmlSchemaParseSequence(ctxt, schema, child);
2657 child = child->next;
2658 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002659 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002660 subtype = (xmlSchemaTypePtr)
2661 xmlSchemaParseGroup(ctxt, schema, child);
2662 child = child->next;
2663 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002664 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002665 if (IS_SCHEMA(child, "simpleType")) {
2666 subtype = (xmlSchemaTypePtr)
2667 xmlSchemaParseSimpleType(ctxt, schema, child);
2668 child = child->next;
2669 type->baseType = subtype;
2670 }
2671 /*
2672 * Facets
2673 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002674 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002675 (IS_SCHEMA(child, "minExclusive")) ||
2676 (IS_SCHEMA(child, "maxInclusive")) ||
2677 (IS_SCHEMA(child, "maxExclusive")) ||
2678 (IS_SCHEMA(child, "totalDigits")) ||
2679 (IS_SCHEMA(child, "fractionDigits")) ||
2680 (IS_SCHEMA(child, "pattern")) ||
2681 (IS_SCHEMA(child, "enumeration")) ||
2682 (IS_SCHEMA(child, "whiteSpace")) ||
2683 (IS_SCHEMA(child, "length")) ||
2684 (IS_SCHEMA(child, "maxLength")) ||
2685 (IS_SCHEMA(child, "minLength"))) {
2686 facet = xmlSchemaParseFacet(ctxt, schema, child);
2687 if (facet != NULL) {
2688 if (lastfacet == NULL) {
2689 type->facets = facet;
2690 lastfacet = facet;
2691 } else {
2692 lastfacet->next = facet;
2693 lastfacet = facet;
2694 }
2695 lastfacet->next = NULL;
2696 }
2697 child = child->next;
2698 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002699 }
2700 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2701 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002702 xmlSchemaPErr2(ctxt, node, child,
2703 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
2704 "Restriction %s has unexpected content\n",
2705 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002706 }
2707 ctxt->container = oldcontainer;
2708 return (type);
2709}
2710
2711/**
2712 * xmlSchemaParseExtension:
2713 * @ctxt: a schema validation context
2714 * @schema: the schema being built
2715 * @node: a subtree containing XML Schema informations
2716 *
2717 * parse a XML schema Extension definition
2718 * *WARNING* this interface is highly subject to change
2719 *
2720 * Returns the type definition or NULL in case of error
2721 */
2722static xmlSchemaTypePtr
2723xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002724 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002725{
2726 xmlSchemaTypePtr type, subtype;
2727 xmlNodePtr child = NULL;
2728 xmlChar name[30];
2729 xmlChar *oldcontainer;
2730
2731 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2732 return (NULL);
2733
2734 oldcontainer = ctxt->container;
2735
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002736 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002737 type = xmlSchemaAddType(ctxt, schema, name);
2738 if (type == NULL)
2739 return (NULL);
2740 type->node = node;
2741 type->type = XML_SCHEMA_TYPE_EXTENSION;
2742 type->id = xmlGetProp(node, BAD_CAST "id");
2743 ctxt->container = name;
2744
2745 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2746 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002747 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
2748 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002749 }
2750 child = node->children;
2751 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002752 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2753 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002754 }
2755 subtype = NULL;
2756
2757 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002758 subtype = xmlSchemaParseAll(ctxt, schema, child);
2759 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002760 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002761 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2762 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002763 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002764 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2765 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002766 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002767 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2768 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002769 }
2770 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002771 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002772 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2773 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002774 xmlSchemaPErr2(ctxt, node, child,
2775 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
2776 "Extension %s has unexpected content\n", type->name,
2777 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002778 }
2779 ctxt->container = oldcontainer;
2780 return (type);
2781}
2782
2783/**
2784 * xmlSchemaParseSimpleContent:
2785 * @ctxt: a schema validation context
2786 * @schema: the schema being built
2787 * @node: a subtree containing XML Schema informations
2788 *
2789 * parse a XML schema SimpleContent definition
2790 * *WARNING* this interface is highly subject to change
2791 *
2792 * Returns the type definition or NULL in case of error
2793 */
2794static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002795xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
2796 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002797{
2798 xmlSchemaTypePtr type, subtype;
2799 xmlNodePtr child = NULL;
2800 xmlChar name[30];
2801
2802 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2803 return (NULL);
2804
2805
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002806 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002807 type = xmlSchemaAddType(ctxt, schema, name);
2808 if (type == NULL)
2809 return (NULL);
2810 type->node = node;
2811 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
2812 type->id = xmlGetProp(node, BAD_CAST "id");
2813
2814 child = node->children;
2815 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002816 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2817 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002818 }
2819 subtype = NULL;
2820 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002821 subtype = (xmlSchemaTypePtr)
2822 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2823 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002824 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002825 subtype = (xmlSchemaTypePtr)
2826 xmlSchemaParseExtension(ctxt, schema, child);
2827 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002828 }
2829 type->subtypes = subtype;
2830 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002831 xmlSchemaPErr2(ctxt, node, child,
2832 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
2833 "SimpleContent %s has unexpected content\n",
2834 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002835 }
2836 return (type);
2837}
2838
2839/**
2840 * xmlSchemaParseComplexContent:
2841 * @ctxt: a schema validation context
2842 * @schema: the schema being built
2843 * @node: a subtree containing XML Schema informations
2844 *
2845 * parse a XML schema ComplexContent definition
2846 * *WARNING* this interface is highly subject to change
2847 *
2848 * Returns the type definition or NULL in case of error
2849 */
2850static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002851xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
2852 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002853{
2854 xmlSchemaTypePtr type, subtype;
2855 xmlNodePtr child = NULL;
2856 xmlChar name[30];
2857
2858 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2859 return (NULL);
2860
2861
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002862 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002863 type = xmlSchemaAddType(ctxt, schema, name);
2864 if (type == NULL)
2865 return (NULL);
2866 type->node = node;
2867 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
2868 type->id = xmlGetProp(node, BAD_CAST "id");
2869
2870 child = node->children;
2871 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002872 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2873 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002874 }
2875 subtype = NULL;
2876 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002877 subtype = (xmlSchemaTypePtr)
2878 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2879 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002880 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002881 subtype = (xmlSchemaTypePtr)
2882 xmlSchemaParseExtension(ctxt, schema, child);
2883 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002884 }
2885 type->subtypes = subtype;
2886 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002887 xmlSchemaPErr2(ctxt, node, child,
2888 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
2889 "ComplexContent %s has unexpected content\n",
2890 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002891 }
2892 return (type);
2893}
2894
2895/**
2896 * xmlSchemaParseComplexType:
2897 * @ctxt: a schema validation context
2898 * @schema: the schema being built
2899 * @node: a subtree containing XML Schema informations
2900 *
2901 * parse a XML schema Complex Type definition
2902 * *WARNING* this interface is highly subject to change
2903 *
2904 * Returns the type definition or NULL in case of error
2905 */
2906static xmlSchemaTypePtr
2907xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2908 xmlNodePtr node)
2909{
2910 xmlSchemaTypePtr type, subtype;
2911 xmlNodePtr child = NULL;
2912 xmlChar *name;
2913 xmlChar *oldcontainer;
2914
2915 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2916 return (NULL);
2917
2918 oldcontainer = ctxt->container;
2919 name = xmlGetProp(node, (const xmlChar *) "name");
2920 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002921 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002922
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002923 snprintf(buf, 99, "anontype%d", ctxt->counter++ + 1);
2924 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00002925 }
2926 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002927 xmlSchemaPErr2(ctxt, node, child,
2928 XML_SCHEMAP_COMPLEXTYPE_NONAME_NOREF,
2929 "complexType has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002930 return (NULL);
2931 }
2932 type = xmlSchemaAddType(ctxt, schema, name);
2933 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002934 xmlFree(name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002935 return (NULL);
2936 }
2937 type->node = node;
2938 type->type = XML_SCHEMA_TYPE_COMPLEX;
2939 type->id = xmlGetProp(node, BAD_CAST "id");
2940 ctxt->container = name;
2941
2942 child = node->children;
2943 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002944 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2945 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002946 }
2947 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002948 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
2949 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002950 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002951 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
2952 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002953 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002954 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002955
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002956 if (IS_SCHEMA(child, "all")) {
2957 subtype = xmlSchemaParseAll(ctxt, schema, child);
2958 child = child->next;
2959 } else if (IS_SCHEMA(child, "choice")) {
2960 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2961 child = child->next;
2962 } else if (IS_SCHEMA(child, "sequence")) {
2963 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2964 child = child->next;
2965 } else if (IS_SCHEMA(child, "group")) {
2966 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2967 child = child->next;
2968 }
2969 if (subtype != NULL)
2970 type->subtypes = subtype;
2971 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002972 }
2973 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002974 xmlSchemaPErr2(ctxt, node, child,
2975 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
2976 "ComplexType %s has unexpected content\n",
2977 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002978 }
2979 ctxt->container = oldcontainer;
2980 xmlFree(name);
2981 return (type);
2982}
2983
2984
2985/**
2986 * xmlSchemaParseSchema:
2987 * @ctxt: a schema validation context
2988 * @node: a subtree containing XML Schema informations
2989 *
2990 * parse a XML schema definition from a node set
2991 * *WARNING* this interface is highly subject to change
2992 *
2993 * Returns the internal XML Schema structure built from the resource or
2994 * NULL in case of error
2995 */
2996static xmlSchemaPtr
2997xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2998{
2999 xmlSchemaPtr schema = NULL;
3000 xmlSchemaAnnotPtr annot;
3001 xmlNodePtr child = NULL;
3002 xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003003 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003004
3005 if ((ctxt == NULL) || (node == NULL))
3006 return (NULL);
3007
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003008 nberrors = ctxt->nberrors;
3009 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003010 if (IS_SCHEMA(node, "schema")) {
3011 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003012 if (schema == NULL)
3013 return (NULL);
3014 schema->targetNamespace =
3015 xmlGetProp(node, BAD_CAST "targetNamespace");
3016 schema->id = xmlGetProp(node, BAD_CAST "id");
3017 schema->version = xmlGetProp(node, BAD_CAST "version");
3018 val = xmlGetProp(node, BAD_CAST "elementFormDefault");
3019 if (val != NULL) {
3020 if (xmlStrEqual(val, BAD_CAST "qualified"))
3021 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3022 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3023 xmlSchemaPErr2(ctxt, node, child,
3024 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3025 "Invalid value %s for elementFormDefault\n",
3026 val, NULL);
3027 }
3028 xmlFree(val);
3029 }
3030 val = xmlGetProp(node, BAD_CAST "attributeFormDefault");
3031 if (val != NULL) {
3032 if (xmlStrEqual(val, BAD_CAST "qualified"))
3033 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3034 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3035 xmlSchemaPErr2(ctxt, node, child,
3036 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3037 "Invalid value %s for attributeFormDefault\n",
3038 val, NULL);
3039 }
3040 xmlFree(val);
3041 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003042
3043 child = node->children;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003044 while ((IS_SCHEMA(child, "include")) ||
3045 (IS_SCHEMA(child, "import")) ||
3046 (IS_SCHEMA(child, "redefine")) ||
3047 (IS_SCHEMA(child, "annotation"))) {
3048 if (IS_SCHEMA(child, "annotation")) {
3049 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3050 if (schema->annot == NULL)
3051 schema->annot = annot;
3052 else
3053 xmlSchemaFreeAnnot(annot);
3054 } else if (IS_SCHEMA(child, "include")) {
3055 TODO} else if (IS_SCHEMA(child, "import")) {
3056 xmlSchemaParseImport(ctxt, schema, child);
3057 } else if (IS_SCHEMA(child, "redefine")) {
3058 TODO}
3059 child = child->next;
3060 }
3061 while (child != NULL) {
3062 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003063 xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003064 child = child->next;
3065 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003066 xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003067 child = child->next;
3068 } else if (IS_SCHEMA(child, "element")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003069 xmlSchemaParseElement(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003070 child = child->next;
3071 } else if (IS_SCHEMA(child, "attribute")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003072 xmlSchemaParseAttribute(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003073 child = child->next;
3074 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003075 xmlSchemaParseAttributeGroup(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003076 child = child->next;
3077 } else if (IS_SCHEMA(child, "group")) {
3078 xmlSchemaParseGroup(ctxt, schema, child);
3079 child = child->next;
3080 } else if (IS_SCHEMA(child, "notation")) {
3081 xmlSchemaParseNotation(ctxt, schema, child);
3082 child = child->next;
3083 } else {
3084 xmlSchemaPErr2(ctxt, node, child,
3085 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3086 "Schemas: unexpected element %s here \n",
3087 child->name, NULL);
3088 child = child->next;
3089 }
3090 while (IS_SCHEMA(child, "annotation")) {
3091 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3092 if (schema->annot == NULL)
3093 schema->annot = annot;
3094 else
3095 xmlSchemaFreeAnnot(annot);
3096 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003097 }
3098 }
3099 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003100 if (ctxt->nberrors != 0) {
3101 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003102 xmlSchemaFree(schema);
3103 schema = NULL;
3104 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003105 }
3106 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003107#ifdef DEBUG
3108 if (schema == NULL)
3109 xmlGenericError(xmlGenericErrorContext,
3110 "xmlSchemaParse() failed\n");
3111#endif
3112
3113 return (schema);
3114}
3115
3116/************************************************************************
3117 * *
3118 * Validating using Schemas *
3119 * *
3120 ************************************************************************/
3121
3122/************************************************************************
3123 * *
3124 * Reading/Writing Schemas *
3125 * *
3126 ************************************************************************/
3127
3128/**
3129 * xmlSchemaNewParserCtxt:
3130 * @URL: the location of the schema
3131 *
3132 * Create an XML Schemas parse context for that file/resource expected
3133 * to contain an XML Schemas file.
3134 *
3135 * Returns the parser context or NULL in case of error
3136 */
3137xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003138xmlSchemaNewParserCtxt(const char *URL)
3139{
Daniel Veillard4255d502002-04-16 15:50:10 +00003140 xmlSchemaParserCtxtPtr ret;
3141
3142 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003143 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003144
3145 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3146 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003147 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3148 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003149 return (NULL);
3150 }
3151 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003152 ret->URL = xmlStrdup((const xmlChar *) URL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003153 return (ret);
3154}
3155
3156/**
Daniel Veillard6045c902002-10-09 21:13:59 +00003157 * xmlSchemaNewMemParserCtxt:
3158 * @buffer: a pointer to a char array containing the schemas
3159 * @size: the size of the array
3160 *
3161 * Create an XML Schemas parse context for that memory buffer expected
3162 * to contain an XML Schemas file.
3163 *
3164 * Returns the parser context or NULL in case of error
3165 */
3166xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003167xmlSchemaNewMemParserCtxt(const char *buffer, int size)
3168{
Daniel Veillard6045c902002-10-09 21:13:59 +00003169 xmlSchemaParserCtxtPtr ret;
3170
3171 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003172 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003173
3174 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3175 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003176 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3177 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003178 return (NULL);
3179 }
3180 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3181 ret->buffer = buffer;
3182 ret->size = size;
3183 return (ret);
3184}
3185
3186/**
Daniel Veillard9d751502003-10-29 13:21:47 +00003187 * xmlSchemaNewDocParserCtxt:
3188 * @doc: a preparsed document tree
3189 *
3190 * Create an XML Schemas parse context for that document.
3191 * NB. The document may be modified during the parsing process.
3192 *
3193 * Returns the parser context or NULL in case of error
3194 */
3195xmlSchemaParserCtxtPtr
3196xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
3197{
3198 xmlSchemaParserCtxtPtr ret;
3199
3200 if (doc == NULL)
3201 return (NULL);
3202
3203 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3204 if (ret == NULL) {
3205 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
3206 NULL);
3207 return (NULL);
3208 }
3209 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3210 ret->doc = doc;
3211
3212 return (ret);
3213}
3214
3215/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003216 * xmlSchemaFreeParserCtxt:
3217 * @ctxt: the schema parser context
3218 *
3219 * Free the resources associated to the schema parser context
3220 */
3221void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003222xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
3223{
Daniel Veillard4255d502002-04-16 15:50:10 +00003224 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003225 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003226 if (ctxt->URL != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003227 xmlFree(ctxt->URL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003228 if (ctxt->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003229 xmlFreeDoc(ctxt->doc);
Daniel Veillard4255d502002-04-16 15:50:10 +00003230 xmlFree(ctxt);
3231}
3232
3233/************************************************************************
3234 * *
3235 * Building the content models *
3236 * *
3237 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003238
Daniel Veillard4255d502002-04-16 15:50:10 +00003239/**
3240 * xmlSchemaBuildAContentModel:
3241 * @type: the schema type definition
3242 * @ctxt: the schema parser context
3243 * @name: the element name whose content is being built
3244 *
3245 * Generate the automata sequence needed for that type
3246 */
3247static void
3248xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003249 xmlSchemaParserCtxtPtr ctxt,
3250 const xmlChar * name)
3251{
Daniel Veillard4255d502002-04-16 15:50:10 +00003252 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003253 xmlGenericError(xmlGenericErrorContext,
3254 "Found unexpected type = NULL in %s content model\n",
3255 name);
3256 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003257 }
3258 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003259 case XML_SCHEMA_TYPE_ANY:
3260 /* TODO : handle the namespace too */
3261 /* TODO : make that a specific transition type */
3262 TODO ctxt->state =
3263 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
3264 BAD_CAST "*", NULL);
3265 break;
3266 case XML_SCHEMA_TYPE_ELEMENT:{
3267 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00003268
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003269 /* TODO : handle the namespace too */
3270 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003271
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003272 if (elem->maxOccurs >= UNBOUNDED) {
3273 if (elem->minOccurs > 1) {
3274 xmlAutomataStatePtr tmp;
3275 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003276
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003277 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3278 oldstate,
3279 NULL);
3280 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003281
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003282 counter = xmlAutomataNewCounter(ctxt->am,
3283 elem->minOccurs -
3284 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00003285
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003286 if (elem->refDecl != NULL) {
3287 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3288 elem->refDecl,
3289 ctxt,
3290 elem->refDecl->
3291 name);
3292 } else {
3293 ctxt->state =
3294 xmlAutomataNewTransition(ctxt->am,
3295 ctxt->state, NULL,
3296 elem->name, type);
3297 }
3298 tmp = ctxt->state;
3299 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3300 counter);
3301 ctxt->state =
3302 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3303 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00003304
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003305 } else {
3306 if (elem->refDecl != NULL) {
3307 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3308 elem->refDecl,
3309 ctxt,
3310 elem->refDecl->
3311 name);
3312 } else {
3313 ctxt->state =
3314 xmlAutomataNewTransition(ctxt->am,
3315 ctxt->state, NULL,
3316 elem->name, type);
3317 }
3318 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3319 oldstate);
3320 if (elem->minOccurs == 0) {
3321 /* basically an elem* */
3322 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3323 ctxt->state);
3324 }
3325 }
3326 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3327 xmlAutomataStatePtr tmp;
3328 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003329
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003330 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3331 oldstate, NULL);
3332 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003333
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003334 counter = xmlAutomataNewCounter(ctxt->am,
3335 elem->minOccurs - 1,
3336 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003337
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003338 if (elem->refDecl != NULL) {
3339 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3340 elem->refDecl, ctxt,
3341 elem->refDecl->name);
3342 } else {
3343 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3344 ctxt->state,
3345 NULL,
3346 elem->name,
3347 type);
3348 }
3349 tmp = ctxt->state;
3350 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3351 counter);
3352 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3353 NULL,
3354 counter);
3355 if (elem->minOccurs == 0) {
3356 /* basically an elem? */
3357 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3358 ctxt->state);
3359 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00003360
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003361 } else {
3362 if (elem->refDecl != NULL) {
3363 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3364 elem->refDecl, ctxt,
3365 elem->refDecl->name);
3366 } else {
3367 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3368 ctxt->state,
3369 NULL,
3370 elem->name,
3371 type);
3372 }
3373 if (elem->minOccurs == 0) {
3374 /* basically an elem? */
3375 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3376 ctxt->state);
3377 }
3378 }
3379 break;
3380 }
3381 case XML_SCHEMA_TYPE_SEQUENCE:{
3382 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003383
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003384 /*
3385 * If max and min occurances are default (1) then
3386 * simply iterate over the subtypes
3387 */
3388 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
3389 subtypes = type->subtypes;
3390 while (subtypes != NULL) {
3391 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3392 subtypes = subtypes->next;
3393 }
3394 } else {
3395 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003396
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003397 if (type->maxOccurs >= UNBOUNDED) {
3398 if (type->minOccurs > 1) {
3399 xmlAutomataStatePtr tmp;
3400 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003401
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003402 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3403 oldstate,
3404 NULL);
3405 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003406
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003407 counter = xmlAutomataNewCounter(ctxt->am,
3408 type->
3409 minOccurs - 1,
3410 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00003411
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003412 subtypes = type->subtypes;
3413 while (subtypes != NULL) {
3414 xmlSchemaBuildAContentModel(subtypes, ctxt,
3415 name);
3416 subtypes = subtypes->next;
3417 }
3418 tmp = ctxt->state;
3419 xmlAutomataNewCountedTrans(ctxt->am, tmp,
3420 oldstate, counter);
3421 ctxt->state =
3422 xmlAutomataNewCounterTrans(ctxt->am, tmp,
3423 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00003424
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003425 } else {
3426 subtypes = type->subtypes;
3427 while (subtypes != NULL) {
3428 xmlSchemaBuildAContentModel(subtypes, ctxt,
3429 name);
3430 subtypes = subtypes->next;
3431 }
3432 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3433 oldstate);
3434 if (type->minOccurs == 0) {
3435 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3436 ctxt->state);
3437 }
3438 }
3439 } else if ((type->maxOccurs > 1)
3440 || (type->minOccurs > 1)) {
3441 xmlAutomataStatePtr tmp;
3442 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003443
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003444 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3445 oldstate,
3446 NULL);
3447 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00003448
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003449 counter = xmlAutomataNewCounter(ctxt->am,
3450 type->minOccurs -
3451 1,
3452 type->maxOccurs -
3453 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003454
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003455 subtypes = type->subtypes;
3456 while (subtypes != NULL) {
3457 xmlSchemaBuildAContentModel(subtypes, ctxt,
3458 name);
3459 subtypes = subtypes->next;
3460 }
3461 tmp = ctxt->state;
3462 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3463 counter);
3464 ctxt->state =
3465 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3466 counter);
3467 if (type->minOccurs == 0) {
3468 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3469 ctxt->state);
3470 }
Daniel Veillardb509f152002-04-17 16:28:10 +00003471
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003472 } else {
3473 subtypes = type->subtypes;
3474 while (subtypes != NULL) {
3475 xmlSchemaBuildAContentModel(subtypes, ctxt,
3476 name);
3477 subtypes = subtypes->next;
3478 }
3479 if (type->minOccurs == 0) {
3480 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3481 ctxt->state);
3482 }
3483 }
3484 }
3485 break;
3486 }
3487 case XML_SCHEMA_TYPE_CHOICE:{
3488 xmlSchemaTypePtr subtypes;
3489 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00003490
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003491 start = ctxt->state;
3492 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00003493
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003494 /*
3495 * iterate over the subtypes and remerge the end with an
3496 * epsilon transition
3497 */
3498 if (type->maxOccurs == 1) {
3499 subtypes = type->subtypes;
3500 while (subtypes != NULL) {
3501 ctxt->state = start;
3502 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3503 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
3504 subtypes = subtypes->next;
3505 }
3506 } else {
3507 int counter;
3508 xmlAutomataStatePtr hop;
3509 int maxOccurs = type->maxOccurs == UNBOUNDED ?
3510 UNBOUNDED : type->maxOccurs - 1;
3511 int minOccurs =
3512 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00003513
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003514 /*
3515 * use a counter to keep track of the number of transtions
3516 * which went through the choice.
3517 */
3518 counter =
3519 xmlAutomataNewCounter(ctxt->am, minOccurs,
3520 maxOccurs);
3521 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00003522
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003523 subtypes = type->subtypes;
3524 while (subtypes != NULL) {
3525 ctxt->state = start;
3526 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3527 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
3528 subtypes = subtypes->next;
3529 }
3530 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
3531 counter);
3532 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
3533 counter);
3534 }
3535 if (type->minOccurs == 0) {
3536 xmlAutomataNewEpsilon(ctxt->am, start, end);
3537 }
3538 ctxt->state = end;
3539 break;
3540 }
3541 case XML_SCHEMA_TYPE_ALL:{
3542 xmlAutomataStatePtr start;
3543 xmlSchemaTypePtr subtypes;
3544 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3545 int lax;
3546
3547 subtypes = type->subtypes;
3548 if (subtypes == NULL)
3549 break;
3550 start = ctxt->state;
3551 while (subtypes != NULL) {
3552 ctxt->state = start;
3553 elem = (xmlSchemaElementPtr) subtypes;
3554
3555 /* TODO : handle the namespace too */
3556 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
3557 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
3558 ctxt->state, elem->name, 1,
3559 1, subtypes);
3560 } else {
3561 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
3562 ctxt->state, elem->name,
3563 elem->minOccurs,
3564 elem->maxOccurs,
3565 subtypes);
3566 }
3567 subtypes = subtypes->next;
3568 }
3569 lax = type->minOccurs == 0;
3570 ctxt->state =
3571 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
3572 lax);
3573 break;
3574 }
3575 case XML_SCHEMA_TYPE_RESTRICTION:
3576 if (type->subtypes != NULL)
3577 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3578 break;
3579 case XML_SCHEMA_TYPE_EXTENSION:
3580 if (type->baseType != NULL) {
3581 xmlSchemaTypePtr subtypes;
3582
3583 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
3584 subtypes = type->subtypes;
3585 while (subtypes != NULL) {
3586 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3587 subtypes = subtypes->next;
3588 }
3589 } else if (type->subtypes != NULL)
3590 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3591 break;
3592 case XML_SCHEMA_TYPE_GROUP:
3593 if (type->subtypes == NULL) {
3594 }
3595 case XML_SCHEMA_TYPE_COMPLEX:
3596 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
3597 if (type->subtypes != NULL)
3598 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3599 break;
3600 default:
3601 xmlGenericError(xmlGenericErrorContext,
3602 "Found unexpected type %d in %s content model\n",
3603 type->type, name);
3604 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003605 }
3606}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003607
Daniel Veillard4255d502002-04-16 15:50:10 +00003608/**
3609 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003610 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00003611 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003612 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00003613 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003614 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00003615 */
3616static void
3617xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003618 xmlSchemaParserCtxtPtr ctxt,
3619 const xmlChar * name)
3620{
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 xmlAutomataStatePtr start;
3622
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003624 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003625 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003626 elem->contentType = XML_SCHEMA_CONTENT_ANY;
3627 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003628 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003630 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003631 if (elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003632 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003633
3634#ifdef DEBUG_CONTENT
3635 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003636 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003637#endif
3638
Daniel Veillard4255d502002-04-16 15:50:10 +00003639 ctxt->am = xmlNewAutomata();
3640 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003641 xmlGenericError(xmlGenericErrorContext,
3642 "Cannot create automata for elem %s\n", name);
3643 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003644 }
3645 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3646 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3647 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00003648 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003649 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
3651 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003652 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003653 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
3654 "Content model of %s is not determinist:\n", name,
3655 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00003656 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00003657#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003658 xmlGenericError(xmlGenericErrorContext,
3659 "Content model of %s:\n", name);
3660 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003661#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00003662 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003663 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003664 xmlFreeAutomata(ctxt->am);
3665 ctxt->am = NULL;
3666}
3667
3668/**
3669 * xmlSchemaRefFixupCallback:
3670 * @elem: the schema element context
3671 * @ctxt: the schema parser context
3672 *
3673 * Free the resources associated to the schema parser context
3674 */
3675static void
3676xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003677 xmlSchemaParserCtxtPtr ctxt,
3678 const xmlChar * name,
3679 const xmlChar * context ATTRIBUTE_UNUSED,
3680 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003681{
3682 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003683 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003684 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003685 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003686
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003687 if (elem->subtypes != NULL) {
3688 xmlSchemaPErr(ctxt, elem->node,
3689 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
3690 "Schemas: element %s have both ref and subtype\n",
3691 name, NULL);
3692 return;
3693 }
3694 elemDecl = xmlHashLookup2(ctxt->schema->elemDecl,
3695 elem->ref, elem->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00003696
3697 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003698 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
3699 "Schemas: element %s ref to %s not found\n",
3700 name, elem->ref);
3701 return;
3702 }
3703 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003704 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003705 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003706
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003707 if (elem->subtypes != NULL) {
3708 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
3709 "Schemas: element %s have both type and subtype\n",
3710 name, NULL);
3711 return;
3712 }
3713 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3714 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00003715
3716 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003717 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
3718 "Schemas: element %s type %s not found\n", name,
3719 elem->namedType);
3720 return;
3721 }
3722 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003723 }
3724}
3725
3726/**
3727 * xmlSchemaTypeFixup:
3728 * @typeDecl: the schema type definition
3729 * @ctxt: the schema parser context
3730 *
3731 * Fixes the content model of the type.
3732 */
3733static void
3734xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003735 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003736{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00003737 if (typeDecl == NULL)
3738 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003739 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003740 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00003741 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003742 switch (typeDecl->type) {
3743 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
3744 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3745 if (typeDecl->subtypes != NULL)
3746 typeDecl->contentType =
3747 typeDecl->subtypes->contentType;
3748 break;
3749 }
3750 case XML_SCHEMA_TYPE_RESTRICTION:{
3751 if (typeDecl->subtypes != NULL)
3752 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003753
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003754 if (typeDecl->base != NULL) {
3755 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00003756
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003757 baseType =
3758 xmlSchemaGetType(ctxt->schema, typeDecl->base,
3759 typeDecl->baseNs);
3760 if (baseType == NULL) {
3761 xmlSchemaPErr(ctxt, typeDecl->node,
3762 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00003763 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003764 name, typeDecl->base);
3765 }
3766 typeDecl->baseType = baseType;
3767 }
3768 if (typeDecl->subtypes == NULL)
3769 /* 1.1.1 */
3770 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3771 else if ((typeDecl->subtypes->subtypes == NULL) &&
3772 ((typeDecl->subtypes->type ==
3773 XML_SCHEMA_TYPE_ALL)
3774 || (typeDecl->subtypes->type ==
3775 XML_SCHEMA_TYPE_SEQUENCE)))
3776 /* 1.1.2 */
3777 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3778 else if ((typeDecl->subtypes->type ==
3779 XML_SCHEMA_TYPE_CHOICE)
3780 && (typeDecl->subtypes->subtypes == NULL))
3781 /* 1.1.3 */
3782 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3783 else {
3784 /* 1.2 and 2.X are applied at the other layer */
3785 typeDecl->contentType =
3786 XML_SCHEMA_CONTENT_ELEMENTS;
3787 }
3788 break;
3789 }
3790 case XML_SCHEMA_TYPE_EXTENSION:{
3791 xmlSchemaContentType explicitContentType;
3792 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00003793
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003794 if (typeDecl->base != NULL) {
3795 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00003796
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003797 baseType =
3798 xmlSchemaGetType(ctxt->schema, typeDecl->base,
3799 typeDecl->baseNs);
3800 if (baseType == NULL) {
3801 xmlSchemaPErr(ctxt, typeDecl->node,
3802 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00003803 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003804 name, typeDecl->base);
3805 }
3806 typeDecl->baseType = baseType;
3807 }
3808 if (typeDecl->subtypes != NULL)
3809 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003810
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003811 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
3812 if (typeDecl->subtypes == NULL)
3813 /* 1.1.1 */
3814 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3815 else if ((typeDecl->subtypes->subtypes == NULL) &&
3816 ((typeDecl->subtypes->type ==
3817 XML_SCHEMA_TYPE_ALL)
3818 || (typeDecl->subtypes->type ==
3819 XML_SCHEMA_TYPE_SEQUENCE)))
3820 /* 1.1.2 */
3821 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3822 else if ((typeDecl->subtypes->type ==
3823 XML_SCHEMA_TYPE_CHOICE)
3824 && (typeDecl->subtypes->subtypes == NULL))
3825 /* 1.1.3 */
3826 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00003827
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003828 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3829 typeDecl->baseNs);
3830 if (base == NULL) {
3831 xmlSchemaPErr(ctxt, typeDecl->node,
3832 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
3833 "Schemas: base type %s of type %s not found\n",
3834 typeDecl->base, name);
3835 return;
3836 }
3837 xmlSchemaTypeFixup(base, ctxt, NULL);
3838 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
3839 /* 2.1 */
3840 typeDecl->contentType = base->contentType;
3841 } else if (base->contentType ==
3842 XML_SCHEMA_CONTENT_EMPTY) {
3843 /* 2.2 imbitable ! */
3844 typeDecl->contentType =
3845 XML_SCHEMA_CONTENT_ELEMENTS;
3846 } else {
3847 /* 2.3 imbitable pareil ! */
3848 typeDecl->contentType =
3849 XML_SCHEMA_CONTENT_ELEMENTS;
3850 }
3851 break;
3852 }
3853 case XML_SCHEMA_TYPE_COMPLEX:{
3854 if (typeDecl->subtypes == NULL) {
3855 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3856 } else {
3857 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3858 typeDecl->contentType =
3859 XML_SCHEMA_CONTENT_MIXED;
3860 else {
3861 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
3862 NULL);
3863 if (typeDecl->subtypes != NULL)
3864 typeDecl->contentType =
3865 typeDecl->subtypes->contentType;
3866 }
3867 }
3868 break;
3869 }
3870 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
3871 if (typeDecl->subtypes == NULL) {
3872 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3873 } else {
3874 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3875 typeDecl->contentType =
3876 XML_SCHEMA_CONTENT_MIXED;
3877 else {
3878 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
3879 NULL);
3880 if (typeDecl->subtypes != NULL)
3881 typeDecl->contentType =
3882 typeDecl->subtypes->contentType;
3883 }
3884 }
3885 break;
3886 }
3887 case XML_SCHEMA_TYPE_SEQUENCE:
3888 case XML_SCHEMA_TYPE_GROUP:
3889 case XML_SCHEMA_TYPE_ALL:
3890 case XML_SCHEMA_TYPE_CHOICE:
3891 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3892 break;
3893 case XML_SCHEMA_TYPE_BASIC:
3894 case XML_SCHEMA_TYPE_ANY:
3895 case XML_SCHEMA_TYPE_FACET:
3896 case XML_SCHEMA_TYPE_SIMPLE:
3897 case XML_SCHEMA_TYPE_UR:
3898 case XML_SCHEMA_TYPE_ELEMENT:
3899 case XML_SCHEMA_TYPE_ATTRIBUTE:
3900 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
3901 case XML_SCHEMA_TYPE_NOTATION:
3902 case XML_SCHEMA_TYPE_LIST:
3903 case XML_SCHEMA_TYPE_UNION:
3904 case XML_SCHEMA_FACET_MININCLUSIVE:
3905 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3906 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3907 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
3908 case XML_SCHEMA_FACET_TOTALDIGITS:
3909 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3910 case XML_SCHEMA_FACET_PATTERN:
3911 case XML_SCHEMA_FACET_ENUMERATION:
3912 case XML_SCHEMA_FACET_WHITESPACE:
3913 case XML_SCHEMA_FACET_LENGTH:
3914 case XML_SCHEMA_FACET_MAXLENGTH:
3915 case XML_SCHEMA_FACET_MINLENGTH:
3916 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
3917 break;
3918 }
3919 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003920#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003921 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003922 xmlGenericError(xmlGenericErrorContext,
3923 "Type of %s : %s:%d :", name,
3924 typeDecl->node->doc->URL,
3925 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003926 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003927 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003928 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003929 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003930 case XML_SCHEMA_CONTENT_SIMPLE:
3931 xmlGenericError(xmlGenericErrorContext, "simple\n");
3932 break;
3933 case XML_SCHEMA_CONTENT_ELEMENTS:
3934 xmlGenericError(xmlGenericErrorContext, "elements\n");
3935 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003936 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003937 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
3938 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003939 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003940 xmlGenericError(xmlGenericErrorContext, "empty\n");
3941 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003942 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003943 xmlGenericError(xmlGenericErrorContext, "mixed\n");
3944 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003945 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003946 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
3947 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003948 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003949 xmlGenericError(xmlGenericErrorContext, "basic\n");
3950 break;
3951 default:
3952 xmlGenericError(xmlGenericErrorContext,
3953 "not registered !!!\n");
3954 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003955 }
3956#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003957}
3958
3959/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003960 * xmlSchemaCheckFacet:
3961 * @facet: the facet
3962 * @typeDecl: the schema type definition
3963 * @ctxt: the schema parser context or NULL
3964 * @name: name of the type
3965 *
3966 * Checks the default values types, especially for facets
3967 *
3968 * Returns 0 if okay or -1 in cae of error
3969 */
3970int
3971xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003972 xmlSchemaTypePtr typeDecl,
3973 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003974{
3975 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
3976 int ret = 0;
3977
3978 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003979 nonNegativeIntegerType =
3980 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
3981 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003982 }
3983 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003984 case XML_SCHEMA_FACET_MININCLUSIVE:
3985 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3986 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3987 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
3988 /*
3989 * Okay we need to validate the value
3990 * at that point.
3991 */
3992 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003993
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003994 vctxt = xmlSchemaNewValidCtxt(NULL);
3995 if (vctxt == NULL)
3996 break;
3997 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3998 facet->value);
3999 facet->val = vctxt->value;
4000 vctxt->value = NULL;
4001 if (facet->val == NULL) {
4002 /* error code */
4003 if (ctxt != NULL) {
4004 xmlSchemaPErr(ctxt, facet->node,
4005 XML_SCHEMAP_INVALID_FACET,
4006 "Schemas: type %s facet value %s invalid\n",
4007 name, facet->value);
4008 }
4009 ret = -1;
4010 }
4011 xmlSchemaFreeValidCtxt(vctxt);
4012 break;
4013 }
4014 case XML_SCHEMA_FACET_ENUMERATION:{
4015 /*
4016 * Okay we need to validate the value
4017 * at that point.
4018 */
4019 xmlSchemaValidCtxtPtr vctxt;
4020 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004021
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004022 vctxt = xmlSchemaNewValidCtxt(NULL);
4023 if (vctxt == NULL)
4024 break;
4025 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4026 facet->value);
4027 if (tmp != 0) {
4028 if (ctxt != NULL) {
4029 xmlSchemaPErr(ctxt, facet->node,
4030 XML_SCHEMAP_INVALID_ENUM,
4031 "Schemas: type %s enumeration value %s invalid\n",
4032 name, facet->value);
4033 }
4034 ret = -1;
4035 }
4036 xmlSchemaFreeValidCtxt(vctxt);
4037 break;
4038 }
4039 case XML_SCHEMA_FACET_PATTERN:
4040 facet->regexp = xmlRegexpCompile(facet->value);
4041 if (facet->regexp == NULL) {
4042 xmlSchemaPErr(ctxt, typeDecl->node,
4043 XML_SCHEMAP_REGEXP_INVALID,
4044 "Schemas: type %s facet regexp %s invalid\n",
4045 name, facet->value);
4046 ret = -1;
4047 }
4048 break;
4049 case XML_SCHEMA_FACET_TOTALDIGITS:
4050 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4051 case XML_SCHEMA_FACET_LENGTH:
4052 case XML_SCHEMA_FACET_MAXLENGTH:
4053 case XML_SCHEMA_FACET_MINLENGTH:{
4054 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004055
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004056 tmp =
4057 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4058 facet->value,
4059 &facet->val);
4060 if (tmp != 0) {
4061 /* error code */
4062 if (ctxt != NULL) {
4063 xmlSchemaPErr(ctxt, facet->node,
4064 XML_SCHEMAP_INVALID_FACET_VALUE,
4065 "Schemas: type %s facet value %s invalid\n",
4066 name, facet->value);
4067 }
4068 ret = -1;
4069 }
4070 break;
4071 }
4072 case XML_SCHEMA_FACET_WHITESPACE:{
4073 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4074 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4075 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4076 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4077 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4078 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4079 } else {
4080 if (ctxt != NULL) {
4081 xmlSchemaPErr(ctxt, facet->node,
4082 XML_SCHEMAP_INVALID_WHITE_SPACE,
4083 "Schemas: type %s whiteSpace value %s invalid\n",
4084 name, facet->value);
4085 }
4086 ret = -1;
4087 }
4088 }
4089 default:
4090 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004091 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004092 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004093}
4094
4095/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004096 * xmlSchemaCheckDefaults:
4097 * @typeDecl: the schema type definition
4098 * @ctxt: the schema parser context
4099 *
4100 * Checks the default values types, especially for facets
4101 */
4102static void
4103xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004104 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004105{
Daniel Veillard4255d502002-04-16 15:50:10 +00004106 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004107 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004108 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004109 if (typeDecl->facets != NULL) {
4110 xmlSchemaFacetPtr facet = typeDecl->facets;
4111
4112 while (facet != NULL) {
4113 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4114 facet = facet->next;
4115 }
4116 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004117 }
4118}
4119
4120/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004121 * xmlSchemaAttrGrpFixup:
4122 * @attrgrpDecl: the schema attribute definition
4123 * @ctxt: the schema parser context
4124 * @name: the attribute name
4125 *
4126 * Fixes finish doing the computations on the attributes definitions
4127 */
4128static void
4129xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004130 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004131{
4132 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004133 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004134 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004135 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004136 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004137 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004138
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004139 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4140 attrgrpDecl->refNs);
4141 if (ref == NULL) {
4142 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4143 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4144 "Schemas: attribute group %s reference %s not found\n",
4145 name, attrgrpDecl->ref);
4146 return;
4147 }
4148 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4149 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004150 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004151 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4152 "Schemas: attribute %s has no attributes nor reference\n",
4153 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004154 }
4155}
4156
4157/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004158 * xmlSchemaAttrFixup:
4159 * @attrDecl: the schema attribute definition
4160 * @ctxt: the schema parser context
4161 * @name: the attribute name
4162 *
4163 * Fixes finish doing the computations on the attributes definitions
4164 */
4165static void
4166xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004167 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004168{
4169 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004170 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004171 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004172 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004173 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004174 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004175
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004176 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4177 attrDecl->typeNs);
4178 if (type == NULL) {
4179 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4180 "Schemas: attribute %s type %s not found\n",
4181 name, attrDecl->typeName);
4182 }
4183 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004184 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004185 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004186
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004187 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4188 attrDecl->refNs);
4189 if (ref == NULL) {
4190 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4191 "Schemas: attribute %s reference %s not found\n",
4192 name, attrDecl->ref);
4193 return;
4194 }
4195 xmlSchemaAttrFixup(ref, ctxt, NULL);
4196 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004197 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004198 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4199 "Schemas: attribute %s has no type nor reference\n",
4200 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004201 }
4202}
4203
4204/**
4205 * xmlSchemaParse:
4206 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004207 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004208 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004209 * XML Shema struture which can be used to validate instances.
4210 * *WARNING* this interface is highly subject to change
4211 *
4212 * Returns the internal XML Schema structure built from the resource or
4213 * NULL in case of error
4214 */
4215xmlSchemaPtr
4216xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4217{
4218 xmlSchemaPtr ret = NULL;
4219 xmlDocPtr doc;
4220 xmlNodePtr root, cur, delete;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004221 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004222
4223 xmlSchemaInitTypes();
4224
Daniel Veillard6045c902002-10-09 21:13:59 +00004225 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004226 return (NULL);
4227
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004228 nberrors = ctxt->nberrors;
4229 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004230 ctxt->counter = 0;
4231 ctxt->container = NULL;
4232
4233 /*
4234 * First step is to parse the input document into an DOM/Infoset
4235 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004236 if (ctxt->URL != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004237 doc = xmlParseFile((const char *) ctxt->URL);
4238 if (doc == NULL) {
4239 xmlSchemaPErr(ctxt, NULL,
4240 XML_SCHEMAP_FAILED_LOAD,
4241 "xmlSchemaParse: could not load %s\n",
4242 ctxt->URL, NULL);
4243 return (NULL);
4244 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004245 } else if (ctxt->buffer != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004246 doc = xmlParseMemory(ctxt->buffer, ctxt->size);
4247 if (doc == NULL) {
4248 xmlSchemaPErr(ctxt, NULL,
4249 XML_SCHEMAP_FAILED_PARSE,
4250 "xmlSchemaParse: could not parse\n",
4251 NULL, NULL);
4252 return (NULL);
4253 }
4254 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
4255 ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard9d751502003-10-29 13:21:47 +00004256 } else if (ctxt->doc != NULL) {
4257 doc = ctxt->doc;
Daniel Veillard6045c902002-10-09 21:13:59 +00004258 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004259 xmlSchemaPErr(ctxt, NULL,
4260 XML_SCHEMAP_NOTHING_TO_PARSE,
4261 "xmlSchemaParse: could not parse\n",
4262 NULL, NULL);
4263 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004264 }
4265
4266 /*
4267 * Then extract the root and Schema parse it
4268 */
4269 root = xmlDocGetRootElement(doc);
4270 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004271 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4272 XML_SCHEMAP_NOROOT,
4273 "schemas has no root", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004274 return (NULL);
4275 }
4276
4277 /*
4278 * Remove all the blank text nodes
4279 */
4280 delete = NULL;
4281 cur = root;
4282 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004283 if (delete != NULL) {
4284 xmlUnlinkNode(delete);
4285 xmlFreeNode(delete);
4286 delete = NULL;
4287 }
4288 if (cur->type == XML_TEXT_NODE) {
4289 if (IS_BLANK_NODE(cur)) {
4290 if (xmlNodeGetSpacePreserve(cur) != 1) {
4291 delete = cur;
4292 }
4293 }
4294 } else if ((cur->type != XML_ELEMENT_NODE) &&
4295 (cur->type != XML_CDATA_SECTION_NODE)) {
4296 delete = cur;
4297 goto skip_children;
4298 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004299
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004300 /*
4301 * Skip to next node
4302 */
4303 if (cur->children != NULL) {
4304 if ((cur->children->type != XML_ENTITY_DECL) &&
4305 (cur->children->type != XML_ENTITY_REF_NODE) &&
4306 (cur->children->type != XML_ENTITY_NODE)) {
4307 cur = cur->children;
4308 continue;
4309 }
4310 }
4311 skip_children:
4312 if (cur->next != NULL) {
4313 cur = cur->next;
4314 continue;
4315 }
4316
4317 do {
4318 cur = cur->parent;
4319 if (cur == NULL)
4320 break;
4321 if (cur == root) {
4322 cur = NULL;
4323 break;
4324 }
4325 if (cur->next != NULL) {
4326 cur = cur->next;
4327 break;
4328 }
4329 } while (cur != NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004330 }
4331 if (delete != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004332 xmlUnlinkNode(delete);
4333 xmlFreeNode(delete);
4334 delete = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004335 }
4336
4337 /*
4338 * Then do the parsing for good
4339 */
4340 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillardb4398962002-04-19 07:01:55 +00004341 if (ret == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004342 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004343 ret->doc = doc;
4344
4345 /*
4346 * Then fix all the references.
4347 */
4348 ctxt->schema = ret;
4349 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004350 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004351
4352 /*
4353 * Then fixup all types properties
4354 */
4355 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4356
4357 /*
4358 * Then build the content model for all elements
4359 */
4360 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004361 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004362
4363 /*
4364 * Then check the defaults part of the type like facets values
4365 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004366 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
4367 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004368
4369 /*
4370 * Then fixup all attributes declarations
4371 */
4372 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4373
Daniel Veillard13e04c62002-04-23 17:51:29 +00004374 /*
4375 * Then fixup all attributes group declarations
4376 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004377 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
4378 ctxt);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004379
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004380 if (ctxt->nberrors != 0) {
4381 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004382 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004383 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004384 return (ret);
4385}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004386
Daniel Veillard4255d502002-04-16 15:50:10 +00004387/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00004388 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00004389 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00004390 * @err: the error callback
4391 * @warn: the warning callback
4392 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00004393 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004394 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004395 */
4396void
4397xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004398 xmlSchemaValidityErrorFunc err,
4399 xmlSchemaValidityWarningFunc warn, void *ctx)
4400{
Daniel Veillard4255d502002-04-16 15:50:10 +00004401 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004402 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004403 ctxt->error = err;
4404 ctxt->warning = warn;
4405 ctxt->userData = ctx;
4406}
4407
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004408/**
4409 * xmlSchemaFacetTypeToString:
4410 * @type: the facet type
4411 *
4412 * Convert the xmlSchemaTypeType to a char string.
4413 *
4414 * Returns the char string representation of the facet type if the
4415 * type is a facet and an "Internal Error" string otherwise.
4416 */
4417static const char *
4418xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
4419{
4420 switch (type) {
4421 case XML_SCHEMA_FACET_PATTERN:
4422 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004423 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004424 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004425 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004426 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004427 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004428 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004429 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004430 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004431 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004432 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004433 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004434 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004435 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004436 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004437 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004438 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004439 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004440 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004441 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004442 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004443 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004444 return ("fractionDigits");
4445 default:
4446 break;
4447 }
4448 return ("Internal Error");
4449}
4450
4451/**
4452 * xmlSchemaValidateFacets:
4453 * @ctxt: a schema validation context
4454 * @base: the base type
4455 * @facets: the list of facets to check
4456 * @value: the lexical repr of the value to validate
4457 * @val: the precomputed value
4458 *
4459 * Check a value against all facet conditions
4460 *
4461 * Returns 0 if the element is schemas valid, a positive error code
4462 * number otherwise and -1 in case of internal or API error.
4463 */
4464static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004465xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
4466 xmlSchemaTypePtr base,
4467 xmlSchemaFacetPtr facets, xmlChar * value)
4468{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004469 int ret = 0;
4470 int tmp = 0;
4471 xmlSchemaTypeType type;
4472 xmlSchemaFacetPtr facet = facets;
4473
4474 while (facet != NULL) {
4475 type = facet->type;
4476 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004477 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004478
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004479 while (facet != NULL) {
4480 tmp =
4481 xmlSchemaValidateFacet(base, facet, value,
4482 ctxt->value);
4483 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004484 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004485 }
4486 facet = facet->next;
4487 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004488 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004489 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004490
4491 if (tmp != 0) {
4492 ret = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004493 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET, "Failed to validate type with facet %s\n", (const xmlChar *) xmlSchemaFacetTypeToString(type), NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004494 }
4495 if (facet != NULL)
4496 facet = facet->next;
4497 }
4498 return (ret);
4499}
4500
Daniel Veillard4255d502002-04-16 15:50:10 +00004501/************************************************************************
4502 * *
4503 * Simple type validation *
4504 * *
4505 ************************************************************************/
4506
4507/**
4508 * xmlSchemaValidateSimpleValue:
4509 * @ctxt: a schema validation context
4510 * @type: the type declaration
4511 * @value: the value to validate
4512 *
4513 * Validate a value against a simple type
4514 *
4515 * Returns 0 if the value is valid, a positive error code
4516 * number otherwise and -1 in case of internal or API error.
4517 */
4518static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004519xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
4520 xmlSchemaTypePtr type, xmlChar * value)
4521{
Daniel Veillard4255d502002-04-16 15:50:10 +00004522 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004523
Daniel Veillard4255d502002-04-16 15:50:10 +00004524 /*
4525 * First normalize the value accordingly to Schema Datatype
4526 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
4527 */
4528 /*
4529 * Then check the normalized value against the lexical space of the
4530 * type.
4531 */
4532 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004533 if (ctxt->value != NULL) {
4534 xmlSchemaFreeValue(ctxt->value);
4535 ctxt->value = NULL;
4536 }
4537 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
4538 ctxt->cur);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004539 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004540 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE, "Failed to validate basic type %s\n", type->name, NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004541 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004542 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004543 xmlSchemaTypePtr base;
4544 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00004545
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004546 base = type->baseType;
4547 if (base != NULL) {
4548 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4549 } else if (type->subtypes != NULL) {
4550
4551 }
4552 /*
4553 * Do not validate facets when working on building the Schemas
4554 */
4555 if (ctxt->schema != NULL) {
4556 if (ret == 0) {
4557 facet = type->facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004558 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004559 }
4560 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004561 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004562 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004563
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004564 base = type->subtypes;
4565 if (base != NULL) {
4566 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4567 } else {
4568 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00004569 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004570 xmlSchemaTypePtr base;
4571 xmlChar *cur, *end, tmp;
4572 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00004573
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004574 base = type->subtypes;
4575 if (base == NULL) {
4576 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
4577 "Internal: List type %s has no base type\n",
4578 type->name, NULL);
4579 return (-1);
4580 }
4581 cur = value;
4582 do {
William M. Brack76e95df2003-10-18 16:20:14 +00004583 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004584 cur++;
4585 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00004586 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004587 end++;
4588 if (end == cur)
4589 break;
4590 tmp = *end;
4591 *end = 0;
4592 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, cur);
4593 if (ret2 != 0)
4594 ret = 1;
4595 *end = tmp;
4596 cur = end;
4597 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004598 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004599 TODO}
4600 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004601}
4602
4603/************************************************************************
4604 * *
4605 * DOM Validation code *
4606 * *
4607 ************************************************************************/
4608
4609static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004610 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004611static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004612 xmlNodePtr elem,
4613 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00004614static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004615 xmlNodePtr elem,
4616 xmlSchemaElementPtr elemDecl,
4617 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004618
4619/**
4620 * xmlSchemaRegisterAttributes:
4621 * @ctxt: a schema validation context
4622 * @attrs: a list of attributes
4623 *
4624 * Register the list of attributes as the set to be validated on that element
4625 *
4626 * Returns -1 in case of error, 0 otherwise
4627 */
4628static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004629xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
4630{
Daniel Veillard4255d502002-04-16 15:50:10 +00004631 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004632 if ((attrs->ns != NULL) &&
4633 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
4634 attrs = attrs->next;
4635 continue;
4636 }
4637 if (ctxt->attrNr >= ctxt->attrMax) {
4638 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00004639
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004640 ctxt->attrMax *= 2;
4641 tmp = (xmlSchemaAttrStatePtr)
4642 xmlRealloc(ctxt->attr, ctxt->attrMax *
4643 sizeof(xmlSchemaAttrState));
4644 if (tmp == NULL) {
4645 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
4646 ctxt->attrMax /= 2;
4647 return (-1);
4648 }
4649 ctxt->attr = tmp;
4650 }
4651 ctxt->attr[ctxt->attrNr].attr = attrs;
4652 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
4653 ctxt->attrNr++;
4654 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004655 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004656 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004657}
4658
4659/**
4660 * xmlSchemaCheckAttributes:
4661 * @ctxt: a schema validation context
4662 * @node: the node carrying it.
4663 *
4664 * Check that the registered set of attributes on the current node
4665 * has been properly validated.
4666 *
4667 * Returns 0 if validity constraints are met, 1 otherwise.
4668 */
4669static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004670xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
4671{
Daniel Veillard4255d502002-04-16 15:50:10 +00004672 int ret = 0;
4673 int i;
4674
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004675 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
4676 if (ctxt->attr[i].attr == NULL)
4677 break;
4678 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
4679 ret = 1;
4680 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
4681 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004682 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004683 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004684}
4685
4686/**
4687 * xmlSchemaValidateSimpleContent:
4688 * @ctxt: a schema validation context
4689 * @elem: an element
4690 * @type: the type declaration
4691 *
4692 * Validate the content of an element expected to be a simple type
4693 *
4694 * Returns 0 if the element is schemas valid, a positive error code
4695 * number otherwise and -1 in case of internal or API error.
4696 */
4697static int
4698xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004699 xmlNodePtr node ATTRIBUTE_UNUSED)
4700{
Daniel Veillard4255d502002-04-16 15:50:10 +00004701 xmlNodePtr child;
4702 xmlSchemaTypePtr type, base;
4703 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004704 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004705
4706 child = ctxt->node;
4707 type = ctxt->type;
4708
4709 /*
4710 * Validation Rule: Element Locally Valid (Type): 3.1.3
4711 */
4712 value = xmlNodeGetContent(child);
4713 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
4714 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004715 case XML_SCHEMA_TYPE_RESTRICTION:{
4716 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00004717
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004718 base = type->baseType;
4719 if (base != NULL) {
4720 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4721 } else {
4722 TODO}
4723 if (ret == 0) {
4724 facet = type->facets;
4725 ret =
4726 xmlSchemaValidateFacets(ctxt, base, facet, value);
4727 }
4728 break;
4729 }
4730 default:
4731 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00004732 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004733 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00004734
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004735 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004736}
4737
4738/**
4739 * xmlSchemaValidateCheckNodeList
4740 * @nodelist: the list of nodes
4741 *
4742 * Check the node list is only made of text nodes and entities pointing
4743 * to text nodes
4744 *
4745 * Returns 1 if true, 0 if false and -1 in case of error
4746 */
4747static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004748xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
4749{
Daniel Veillard4255d502002-04-16 15:50:10 +00004750 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004751 if (nodelist->type == XML_ENTITY_REF_NODE) {
4752 TODO /* implement recursion in the entity content */
4753 }
4754 if ((nodelist->type != XML_TEXT_NODE) &&
4755 (nodelist->type != XML_COMMENT_NODE) &&
4756 (nodelist->type != XML_PI_NODE) &&
4757 (nodelist->type != XML_PI_NODE)) {
4758 return (0);
4759 }
4760 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004761 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004762 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004763}
4764
4765/**
4766 * xmlSchemaSkipIgnored:
4767 * @ctxt: a schema validation context
4768 * @type: the current type context
4769 * @node: the top node.
4770 *
4771 * Skip ignorable nodes in that context
4772 *
4773 * Returns the new sibling
4774 * number otherwise and -1 in case of internal or API error.
4775 */
4776static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00004777xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004778 xmlSchemaTypePtr type, xmlNodePtr node)
4779{
Daniel Veillard4255d502002-04-16 15:50:10 +00004780 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004781
Daniel Veillard4255d502002-04-16 15:50:10 +00004782 /*
4783 * TODO complete and handle entities
4784 */
4785 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004786 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00004787 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004788 ((node->type == XML_COMMENT_NODE) ||
4789 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
4790 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
4791 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
4792 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004793 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004794 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004795}
4796
4797/**
4798 * xmlSchemaValidateCallback:
4799 * @ctxt: a schema validation context
4800 * @name: the name of the element detected (might be NULL)
4801 * @type: the type
4802 *
4803 * A transition has been made in the automata associated to an element
4804 * content model
4805 */
4806static void
4807xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004808 const xmlChar * name ATTRIBUTE_UNUSED,
4809 xmlSchemaTypePtr type, xmlNodePtr node)
4810{
Daniel Veillard4255d502002-04-16 15:50:10 +00004811 xmlSchemaTypePtr oldtype = ctxt->type;
4812 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004813
Daniel Veillard4255d502002-04-16 15:50:10 +00004814#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00004815 xmlGenericError(xmlGenericErrorContext,
4816 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004817 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004818#endif
4819 ctxt->type = type;
4820 ctxt->node = node;
4821 xmlSchemaValidateContent(ctxt, node);
4822 ctxt->type = oldtype;
4823 ctxt->node = oldnode;
4824}
4825
4826
4827#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004828
Daniel Veillard4255d502002-04-16 15:50:10 +00004829/**
4830 * xmlSchemaValidateSimpleRestrictionType:
4831 * @ctxt: a schema validation context
4832 * @node: the top node.
4833 *
4834 * Validate the content of a restriction type.
4835 *
4836 * Returns 0 if the element is schemas valid, a positive error code
4837 * number otherwise and -1 in case of internal or API error.
4838 */
4839static int
4840xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
4841 xmlNodePtr node)
4842{
4843 xmlNodePtr child;
4844 xmlSchemaTypePtr type;
4845 int ret;
4846
4847 child = ctxt->node;
4848 type = ctxt->type;
4849
4850 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004851 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004852 return (-1);
4853 }
4854 /*
4855 * Only text and text based entities references shall be found there
4856 */
4857 ret = xmlSchemaValidateCheckNodeList(child);
4858 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004859 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004860 return (-1);
4861 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004862 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004863 return (-1);
4864 }
4865 ctxt->type = type->subtypes;
4866 xmlSchemaValidateContent(ctxt, node);
4867 ctxt->type = type;
4868 return (ret);
4869}
4870#endif
4871
4872/**
4873 * xmlSchemaValidateSimpleType:
4874 * @ctxt: a schema validation context
4875 * @node: the top node.
4876 *
4877 * Validate the content of an simple type.
4878 *
4879 * Returns 0 if the element is schemas valid, a positive error code
4880 * number otherwise and -1 in case of internal or API error.
4881 */
4882static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004883xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
4884{
Daniel Veillard4255d502002-04-16 15:50:10 +00004885 xmlNodePtr child;
4886 xmlSchemaTypePtr type;
4887 xmlAttrPtr attr;
4888 int ret;
4889
4890 child = ctxt->node;
4891 type = ctxt->type;
4892
4893 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004894 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
4895 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004896 }
4897 /*
4898 * Only text and text based entities references shall be found there
4899 */
4900 ret = xmlSchemaValidateCheckNodeList(child);
4901 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004902 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
4903 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004904 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004905 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
4906 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004907 }
4908 /*
4909 * Validation Rule: Element Locally Valid (Type): 3.1.1
4910 */
4911 attr = node->properties;
4912 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004913 if ((attr->ns == NULL) ||
4914 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
4915 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
4916 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
4917 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
4918 (!xmlStrEqual
4919 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
4920 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
4921 return (ctxt->err);
4922 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004923 }
4924
4925 ctxt->type = type->subtypes;
4926 ret = xmlSchemaValidateSimpleContent(ctxt, node);
4927 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004928 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004929}
4930
4931/**
4932 * xmlSchemaValidateElementType:
4933 * @ctxt: a schema validation context
4934 * @node: the top node.
4935 *
4936 * Validate the content of an element type.
4937 * Validation Rule: Element Locally Valid (Complex Type)
4938 *
4939 * Returns 0 if the element is schemas valid, a positive error code
4940 * number otherwise and -1 in case of internal or API error.
4941 */
4942static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004943xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
4944{
Daniel Veillard4255d502002-04-16 15:50:10 +00004945 xmlNodePtr child;
4946 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004947 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00004948 xmlSchemaElementPtr decl;
4949 int ret, attrBase;
4950
4951 oldregexp = ctxt->regexp;
4952
4953 child = ctxt->node;
4954 type = ctxt->type;
4955
4956 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004957 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
4958 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004959 }
4960 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004961 if (type->minOccurs > 0) {
4962 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
4963 }
4964 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00004965 }
4966
4967 /*
4968 * Verify the element matches
4969 */
4970 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004971 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
4972 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00004973 }
4974 /*
4975 * Verify the attributes
4976 */
4977 attrBase = ctxt->attrBase;
4978 ctxt->attrBase = ctxt->attrNr;
4979 xmlSchemaRegisterAttributes(ctxt, child->properties);
4980 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
4981 /*
4982 * Verify the element content recursively
4983 */
4984 decl = (xmlSchemaElementPtr) type;
4985 oldregexp = ctxt->regexp;
4986 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004987 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
4988 (xmlRegExecCallbacks)
4989 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004990#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004991 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004992#endif
4993 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004994 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
4995 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00004996
4997 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004998 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004999#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005000 xmlGenericError(xmlGenericErrorContext,
5001 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005002#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005003 if (ret == 0) {
5004 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
5005 } else if (ret < 0) {
5006 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005007#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005008 } else {
5009 xmlGenericError(xmlGenericErrorContext,
5010 "Element %s content check succeeded\n",
5011 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005012
5013#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005014 }
5015 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005016 }
5017 /*
5018 * Verify that all attributes were Schemas-validated
5019 */
5020 xmlSchemaCheckAttributes(ctxt, node);
5021 ctxt->attrNr = ctxt->attrBase;
5022 ctxt->attrBase = attrBase;
5023
5024 ctxt->regexp = oldregexp;
5025
5026 ctxt->node = child;
5027 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005028 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005029}
5030
5031/**
5032 * xmlSchemaValidateBasicType:
5033 * @ctxt: a schema validation context
5034 * @node: the top node.
5035 *
5036 * Validate the content of an element expected to be a basic type type
5037 *
5038 * Returns 0 if the element is schemas valid, a positive error code
5039 * number otherwise and -1 in case of internal or API error.
5040 */
5041static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005042xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5043{
Daniel Veillard4255d502002-04-16 15:50:10 +00005044 int ret;
5045 xmlNodePtr child, cur;
5046 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005047 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005048
5049 child = ctxt->node;
5050 type = ctxt->type;
5051
5052 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005053 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5054 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005055 }
5056 /*
5057 * First check the content model of the node.
5058 */
5059 cur = child;
5060 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005061 switch (cur->type) {
5062 case XML_TEXT_NODE:
5063 case XML_CDATA_SECTION_NODE:
5064 case XML_PI_NODE:
5065 case XML_COMMENT_NODE:
5066 case XML_XINCLUDE_START:
5067 case XML_XINCLUDE_END:
5068 break;
5069 case XML_ENTITY_REF_NODE:
5070 case XML_ENTITY_NODE:
5071 TODO break;
5072 case XML_ELEMENT_NODE:
5073 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5074 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005075 case XML_ATTRIBUTE_NODE:
5076 case XML_DOCUMENT_NODE:
5077 case XML_DOCUMENT_TYPE_NODE:
5078 case XML_DOCUMENT_FRAG_NODE:
5079 case XML_NOTATION_NODE:
5080 case XML_HTML_DOCUMENT_NODE:
5081 case XML_DTD_NODE:
5082 case XML_ELEMENT_DECL:
5083 case XML_ATTRIBUTE_DECL:
5084 case XML_ENTITY_DECL:
5085 case XML_NAMESPACE_DECL:
5086#ifdef LIBXML_DOCB_ENABLED
5087 case XML_DOCB_DOCUMENT_NODE:
5088#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005089 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5090 return (ctxt->err);
5091 }
5092 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005093 }
5094 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005095 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005096 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005097 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005098
5099 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005100 xmlSchemaFreeValue(ctxt->value);
5101 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005102 }
5103 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5104 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005105 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005106 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005107 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE, "Element %s: failed to validate basic type %s\n", node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005108 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005109 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005110}
5111
5112/**
5113 * xmlSchemaValidateComplexType:
5114 * @ctxt: a schema validation context
5115 * @node: the top node.
5116 *
5117 * Validate the content of an element expected to be a complex type type
5118 * xmlschema-1.html#cvc-complex-type
5119 * Validation Rule: Element Locally Valid (Complex Type)
5120 *
5121 * Returns 0 if the element is schemas valid, a positive error code
5122 * number otherwise and -1 in case of internal or API error.
5123 */
5124static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005125xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5126{
Daniel Veillard4255d502002-04-16 15:50:10 +00005127 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005128 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005129 int ret;
5130
5131 child = ctxt->node;
5132 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005133 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005134
Daniel Veillard4255d502002-04-16 15:50:10 +00005135 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005136 case XML_SCHEMA_CONTENT_EMPTY:
5137 if (child != NULL) {
5138 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5139 }
5140 if (type->attributes != NULL) {
5141 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5142 }
5143 subtype = type->subtypes;
5144 while (subtype != NULL) {
5145 ctxt->type = subtype;
5146 xmlSchemaValidateComplexType(ctxt, node);
5147 subtype = subtype->next;
5148 }
5149 break;
5150 case XML_SCHEMA_CONTENT_ELEMENTS:
5151 case XML_SCHEMA_CONTENT_MIXED:
5152 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5153 /*
5154 * Skip ignorable nodes in that context
5155 */
5156 child = xmlSchemaSkipIgnored(ctxt, type, child);
5157 while (child != NULL) {
5158 if (child->type == XML_ELEMENT_NODE) {
5159 ret = xmlRegExecPushString(ctxt->regexp,
5160 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005161#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005162 if (ret < 0)
5163 xmlGenericError(xmlGenericErrorContext,
5164 " --> %s Error\n", child->name);
5165 else
5166 xmlGenericError(xmlGenericErrorContext,
5167 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005168#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005169 }
5170 child = child->next;
5171 /*
5172 * Skip ignorable nodes in that context
5173 */
5174 child = xmlSchemaSkipIgnored(ctxt, type, child);
5175 }
5176 break;
5177 case XML_SCHEMA_CONTENT_BASIC:{
5178 if (type->subtypes != NULL) {
5179 ctxt->type = type->subtypes;
5180 xmlSchemaValidateComplexType(ctxt, node);
5181 }
5182 if (type->baseType != NULL) {
5183 ctxt->type = type->baseType;
5184 xmlSchemaValidateBasicType(ctxt, node);
5185 }
5186 if (type->attributes != NULL) {
5187 xmlSchemaValidateAttributes(ctxt, node,
5188 type->attributes);
5189 }
5190 ctxt->type = type;
5191 break;
5192 }
5193 default:
5194 TODO xmlGenericError(xmlGenericErrorContext,
5195 "unimplemented content type %d\n",
5196 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005197 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005198 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005199}
5200
5201/**
5202 * xmlSchemaValidateContent:
5203 * @ctxt: a schema validation context
5204 * @elem: an element
5205 * @type: the type declaration
5206 *
5207 * Validate the content of an element against the type.
5208 *
5209 * Returns 0 if the element is schemas valid, a positive error code
5210 * number otherwise and -1 in case of internal or API error.
5211 */
5212static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005213xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5214{
Daniel Veillard4255d502002-04-16 15:50:10 +00005215 xmlNodePtr child;
5216 xmlSchemaTypePtr type;
5217
5218 child = ctxt->node;
5219 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005220 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005221
Daniel Veillarde19fc232002-04-22 16:01:24 +00005222 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005223 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00005224
Daniel Veillard4255d502002-04-16 15:50:10 +00005225 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005226 case XML_SCHEMA_TYPE_ANY:
5227 /* Any type will do it, fine */
5228 TODO /* handle recursivity */
5229 break;
5230 case XML_SCHEMA_TYPE_COMPLEX:
5231 xmlSchemaValidateComplexType(ctxt, node);
5232 break;
5233 case XML_SCHEMA_TYPE_ELEMENT:{
5234 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5235
5236 /*
5237 * Handle element reference here
5238 */
5239 if (decl->ref != NULL) {
5240 if (decl->refDecl == NULL) {
5241 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
5242 return (-1);
5243 }
5244 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5245 decl = decl->refDecl;
5246 }
5247 xmlSchemaValidateElementType(ctxt, node);
5248 ctxt->type = type;
5249 break;
5250 }
5251 case XML_SCHEMA_TYPE_BASIC:
5252 xmlSchemaValidateBasicType(ctxt, node);
5253 break;
5254 case XML_SCHEMA_TYPE_FACET:
5255 TODO break;
5256 case XML_SCHEMA_TYPE_SIMPLE:
5257 xmlSchemaValidateSimpleType(ctxt, node);
5258 break;
5259 case XML_SCHEMA_TYPE_SEQUENCE:
5260 TODO break;
5261 case XML_SCHEMA_TYPE_CHOICE:
5262 TODO break;
5263 case XML_SCHEMA_TYPE_ALL:
5264 TODO break;
5265 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5266 TODO break;
5267 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5268 TODO break;
5269 case XML_SCHEMA_TYPE_UR:
5270 TODO break;
5271 case XML_SCHEMA_TYPE_RESTRICTION:
5272 /*xmlSchemaValidateRestrictionType(ctxt, node); */
5273 TODO break;
5274 case XML_SCHEMA_TYPE_EXTENSION:
5275 TODO break;
5276 case XML_SCHEMA_TYPE_ATTRIBUTE:
5277 TODO break;
5278 case XML_SCHEMA_TYPE_GROUP:
5279 TODO break;
5280 case XML_SCHEMA_TYPE_NOTATION:
5281 TODO break;
5282 case XML_SCHEMA_TYPE_LIST:
5283 TODO break;
5284 case XML_SCHEMA_TYPE_UNION:
5285 TODO break;
5286 case XML_SCHEMA_FACET_MININCLUSIVE:
5287 TODO break;
5288 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5289 TODO break;
5290 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5291 TODO break;
5292 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5293 TODO break;
5294 case XML_SCHEMA_FACET_TOTALDIGITS:
5295 TODO break;
5296 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5297 TODO break;
5298 case XML_SCHEMA_FACET_PATTERN:
5299 TODO break;
5300 case XML_SCHEMA_FACET_ENUMERATION:
5301 TODO break;
5302 case XML_SCHEMA_FACET_WHITESPACE:
5303 TODO break;
5304 case XML_SCHEMA_FACET_LENGTH:
5305 TODO break;
5306 case XML_SCHEMA_FACET_MAXLENGTH:
5307 TODO break;
5308 case XML_SCHEMA_FACET_MINLENGTH:
5309 TODO break;
5310 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5311 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00005312 }
5313 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5314
5315 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005316 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005317 ctxt->node = ctxt->node->next;
5318 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005319 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005320}
5321
5322/**
5323 * xmlSchemaValidateType:
5324 * @ctxt: a schema validation context
5325 * @elem: an element
5326 * @type: the list of type declarations
5327 *
5328 * Validate the content of an element against the types.
5329 *
5330 * Returns 0 if the element is schemas valid, a positive error code
5331 * number otherwise and -1 in case of internal or API error.
5332 */
5333static int
5334xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005335 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
5336{
Daniel Veillard4255d502002-04-16 15:50:10 +00005337 xmlChar *nil;
5338
Daniel Veillard2db8c122003-07-08 12:16:59 +00005339 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005340 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00005341
Daniel Veillard4255d502002-04-16 15:50:10 +00005342 /*
5343 * 3.3.4 : 2
5344 */
5345 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005346 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
5347 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005348 }
5349 /*
5350 * 3.3.4: 3
5351 */
5352 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5353 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005354 /* 3.3.4: 3.2 */
5355 if (xmlStrEqual(nil, BAD_CAST "true")) {
5356 if (elem->children != NULL) {
5357 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
5358 return (ctxt->err);
5359 }
5360 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
5361 (elemDecl->value != NULL)) {
5362 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
5363 return (ctxt->err);
5364 }
5365 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005366 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005367 /* 3.3.4: 3.1 */
5368 if (nil != NULL) {
5369 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
5370 xmlFree(nil);
5371 return (ctxt->err);
5372 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005373 }
5374
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005375 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00005376
5377 ctxt->type = elemDecl->subtypes;
5378 ctxt->node = elem->children;
5379 xmlSchemaValidateContent(ctxt, elem);
5380 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005381
5382 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005383}
5384
5385
5386/**
5387 * xmlSchemaValidateAttributes:
5388 * @ctxt: a schema validation context
5389 * @elem: an element
5390 * @attributes: the list of attribute declarations
5391 *
5392 * Validate the attributes of an element.
5393 *
5394 * Returns 0 if the element is schemas valid, a positive error code
5395 * number otherwise and -1 in case of internal or API error.
5396 */
5397static int
5398xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005399 xmlSchemaAttributePtr attributes)
5400{
Daniel Veillard4255d502002-04-16 15:50:10 +00005401 int i, ret;
5402 xmlAttrPtr attr;
5403 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005404 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005405
5406 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005407 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005408 while (attributes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005409 /*
5410 * Handle attribute groups
5411 */
5412 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5413 group = (xmlSchemaAttributeGroupPtr) attributes;
5414 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
5415 attributes = group->next;
5416 continue;
5417 }
5418 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5419 attr = ctxt->attr[i].attr;
5420 if (attr == NULL)
5421 continue;
5422 if (attributes->ref != NULL) {
5423 if (!xmlStrEqual(attr->name, attributes->ref))
5424 continue;
5425 if (attr->ns != NULL) {
5426 if ((attributes->refNs == NULL) ||
5427 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
5428 continue;
5429 } else if (attributes->refNs != NULL) {
5430 continue;
5431 }
5432 } else {
5433 if (!xmlStrEqual(attr->name, attributes->name))
5434 continue;
5435 /*
5436 * TODO: handle the mess about namespaces here.
5437 */
5438 if ((attr->ns != NULL) /* || (attributes->ns != NULL) */ ) {
5439 TODO}
5440 }
5441 ctxt->cur = (xmlNodePtr) attributes;
5442 if (attributes->subtypes == NULL) {
5443 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
5444 continue;
5445 }
5446 value = xmlNodeListGetString(elem->doc, attr->children, 1);
5447 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
5448 value);
5449 if (ret != 0) {
5450 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
5451 } else {
5452 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
5453 }
5454 if (value != NULL) {
5455 xmlFree(value);
5456 }
5457 }
5458 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005459 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005460 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005461}
5462
5463/**
5464 * xmlSchemaValidateElement:
5465 * @ctxt: a schema validation context
5466 * @elem: an element
5467 *
5468 * Validate an element in a tree
5469 *
5470 * Returns 0 if the element is schemas valid, a positive error code
5471 * number otherwise and -1 in case of internal or API error.
5472 */
5473static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005474xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
5475{
Daniel Veillard4255d502002-04-16 15:50:10 +00005476 xmlSchemaElementPtr elemDecl;
5477 int ret, attrBase;
5478
5479 if (elem->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005480 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5481 elem->name, elem->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005482 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005483 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5484 elem->name, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005485 /*
5486 * 3.3.4 : 1
5487 */
5488 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005489 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
5490 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005491 }
5492 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005493 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
5494 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005495 }
5496 /*
5497 * Verify the attributes
5498 */
5499 attrBase = ctxt->attrBase;
5500 ctxt->attrBase = ctxt->attrNr;
5501 xmlSchemaRegisterAttributes(ctxt, elem->properties);
5502 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5503 /*
5504 * Verify the element content recursively
5505 */
5506 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005507 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
5508 (xmlRegExecCallbacks)
5509 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005510#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005511 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005512#endif
5513 }
5514 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005515 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005516 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005517#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005518 xmlGenericError(xmlGenericErrorContext,
5519 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005520#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005521 if (ret == 0) {
5522 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
5523 } else if (ret < 0) {
5524 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005525#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005526 } else {
5527 xmlGenericError(xmlGenericErrorContext,
5528 "Element %s content check succeeded\n",
5529 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005530
5531#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005532 }
5533 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005534 }
5535 /*
5536 * Verify that all attributes were Schemas-validated
5537 */
5538 xmlSchemaCheckAttributes(ctxt, elem);
5539 ctxt->attrNr = ctxt->attrBase;
5540 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005541
5542 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005543}
5544
5545/**
5546 * xmlSchemaValidateDocument:
5547 * @ctxt: a schema validation context
5548 * @doc: a parsed document tree
5549 *
5550 * Validate a document tree in memory.
5551 *
5552 * Returns 0 if the document is schemas valid, a positive error code
5553 * number otherwise and -1 in case of internal or API error.
5554 */
5555static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005556xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
5557{
Daniel Veillard4255d502002-04-16 15:50:10 +00005558 xmlNodePtr root;
5559 xmlSchemaElementPtr elemDecl;
5560
5561 root = xmlDocGetRootElement(doc);
5562 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005563 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
5564 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005565 }
5566 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005567 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5568 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005569 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005570 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5571 root->name, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005572 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005573 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005574 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005575 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005576 }
5577 /*
5578 * Okay, start the recursive validation
5579 */
5580 xmlSchemaValidateElement(ctxt, root);
5581
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005582 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005583}
5584
5585/************************************************************************
5586 * *
5587 * SAX Validation code *
5588 * *
5589 ************************************************************************/
5590
5591/************************************************************************
5592 * *
5593 * Validation interfaces *
5594 * *
5595 ************************************************************************/
5596
5597/**
5598 * xmlSchemaNewValidCtxt:
5599 * @schema: a precompiled XML Schemas
5600 *
5601 * Create an XML Schemas validation context based on the given schema
5602 *
5603 * Returns the validation context or NULL in case of error
5604 */
5605xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005606xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
5607{
Daniel Veillard4255d502002-04-16 15:50:10 +00005608 xmlSchemaValidCtxtPtr ret;
5609
5610 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
5611 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005612 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005613 return (NULL);
5614 }
5615 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
5616 ret->schema = schema;
5617 ret->attrNr = 0;
5618 ret->attrMax = 10;
5619 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005620 sizeof
5621 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00005622 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005623 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
5624 free(ret);
5625 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005626 }
5627 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
5628 return (ret);
5629}
5630
5631/**
5632 * xmlSchemaFreeValidCtxt:
5633 * @ctxt: the schema validation context
5634 *
5635 * Free the resources associated to the schema validation context
5636 */
5637void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005638xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
5639{
Daniel Veillard4255d502002-04-16 15:50:10 +00005640 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005641 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005642 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005643 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00005644 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005645 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005646 xmlFree(ctxt);
5647}
5648
5649/**
5650 * xmlSchemaSetValidErrors:
5651 * @ctxt: a schema validation context
5652 * @err: the error function
5653 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00005654 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00005655 *
5656 * Set the error and warning callback informations
5657 */
5658void
5659xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005660 xmlSchemaValidityErrorFunc err,
5661 xmlSchemaValidityWarningFunc warn, void *ctx)
5662{
Daniel Veillard4255d502002-04-16 15:50:10 +00005663 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005664 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005665 ctxt->error = err;
5666 ctxt->warning = warn;
5667 ctxt->userData = ctx;
5668}
5669
5670/**
5671 * xmlSchemaValidateDoc:
5672 * @ctxt: a schema validation context
5673 * @doc: a parsed document tree
5674 *
5675 * Validate a document tree in memory.
5676 *
5677 * Returns 0 if the document is schemas valid, a positive error code
5678 * number otherwise and -1 in case of internal or API error.
5679 */
5680int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005681xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
5682{
Daniel Veillard4255d502002-04-16 15:50:10 +00005683 int ret;
5684
5685 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005686 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005687
5688 ctxt->doc = doc;
5689 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005690 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005691}
5692
5693/**
5694 * xmlSchemaValidateStream:
5695 * @ctxt: a schema validation context
5696 * @input: the input to use for reading the data
5697 * @enc: an optional encoding information
5698 * @sax: a SAX handler for the resulting events
5699 * @user_data: the context to provide to the SAX handler.
5700 *
5701 * Validate a document tree in memory.
5702 *
5703 * Returns 0 if the document is schemas valid, a positive error code
5704 * number otherwise and -1 in case of internal or API error.
5705 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005706int
Daniel Veillard4255d502002-04-16 15:50:10 +00005707xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005708 xmlParserInputBufferPtr input, xmlCharEncoding enc,
5709 xmlSAXHandlerPtr sax, void *user_data)
5710{
Daniel Veillard4255d502002-04-16 15:50:10 +00005711 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005712 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005713 ctxt->input = input;
5714 ctxt->enc = enc;
5715 ctxt->sax = sax;
5716 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005717 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005718}
5719
5720#endif /* LIBXML_SCHEMAS_ENABLED */