blob: a86ddabae06b6e3f6e8c075696b55b02aa122754 [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 Veillard4255d502002-04-16 15:50:10 +000068
Daniel Veillardd0c9c322003-10-10 00:49:42 +000069 xmlSchemaPtr schema; /* The schema in use */
70 xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +000071 int counter;
72
Daniel Veillardd0c9c322003-10-10 00:49:42 +000073 xmlChar *URL;
74 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +000075
Daniel Veillardd0c9c322003-10-10 00:49:42 +000076 const char *buffer;
77 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +000078
Daniel Veillard4255d502002-04-16 15:50:10 +000079 /*
80 * Used to build complex element content models
81 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000082 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +000083 xmlAutomataStatePtr start;
84 xmlAutomataStatePtr end;
85 xmlAutomataStatePtr state;
86};
87
88
89#define XML_SCHEMAS_ATTR_UNKNOWN 1
90#define XML_SCHEMAS_ATTR_CHECKED 2
91
92typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
93typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
94struct _xmlSchemaAttrState {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000095 xmlAttrPtr attr;
96 int state;
Daniel Veillard4255d502002-04-16 15:50:10 +000097};
98
99/**
100 * xmlSchemaValidCtxt:
101 *
102 * A Schemas validation context
103 */
104
105struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000106 void *userData; /* user specific data block */
107 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
108 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard4255d502002-04-16 15:50:10 +0000109
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000110 xmlSchemaPtr schema; /* The schema in use */
111 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000112 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000113 xmlCharEncoding enc;
114 xmlSAXHandlerPtr sax;
115 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000116
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000117 xmlDocPtr myDoc;
118 int err;
119 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000120
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000121 xmlNodePtr node;
122 xmlNodePtr cur;
123 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000124
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000125 xmlRegExecCtxtPtr regexp;
126 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000127
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000128 int attrNr;
129 int attrBase;
130 int attrMax;
131 xmlSchemaAttrStatePtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +0000132};
133
134
135/************************************************************************
136 * *
137 * Some predeclarations *
138 * *
139 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000140static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
141 xmlSchemaTypePtr type,
142 xmlChar * value);
143
144/************************************************************************
145 * *
146 * Datatype error handlers *
147 * *
148 ************************************************************************/
149
150/**
151 * xmlSchemaPErrMemory:
152 * @node: a context node
153 * @extra: extra informations
154 *
155 * Handle an out of memory condition
156 */
157static void
158xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
159 const char *extra, xmlNodePtr node)
160{
161 if (ctxt != NULL)
162 ctxt->nberrors++;
163 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
164 extra);
165}
166
167/**
168 * xmlSchemaPErr:
169 * @ctxt: the parsing context
170 * @node: the context node
171 * @error: the error code
172 * @msg: the error message
173 * @str1: extra data
174 * @str2: extra data
175 *
176 * Handle a parser error
177 */
178static void
179xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
180 const char *msg, const xmlChar * str1, const xmlChar * str2)
181{
182 xmlGenericErrorFunc channel = NULL;
183 void *data = NULL;
184
185 if (ctxt != NULL) {
186 ctxt->nberrors++;
187 channel = ctxt->error;
188 data = ctxt->userData;
189 }
190 __xmlRaiseError(channel, data, ctxt, node, XML_FROM_SCHEMASP,
191 error, XML_ERR_ERROR, NULL, 0,
192 (const char *) str1, (const char *) str2, NULL, 0, 0,
193 msg, str1, str2);
194}
195
196/**
197 * xmlSchemaPErr2:
198 * @ctxt: the parsing context
199 * @node: the context node
200 * @node: the current child
201 * @error: the error code
202 * @msg: the error message
203 * @str1: extra data
204 * @str2: extra data
205 *
206 * Handle a parser error
207 */
208static void
209xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
210 xmlNodePtr child, int error,
211 const char *msg, const xmlChar * str1, const xmlChar * str2)
212{
213 if (child != NULL)
214 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
215 else
216 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
217}
218
219/**
220 * xmlSchemaVTypeErrMemory:
221 * @node: a context node
222 * @extra: extra informations
223 *
224 * Handle an out of memory condition
225 */
226static void
227xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
228 const char *extra, xmlNodePtr node)
229{
230 if (ctxt != NULL) {
231 ctxt->nberrors++;
232 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
233 }
234 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
235 extra);
236}
237
238/**
239 * xmlSchemaVErr3:
240 * @ctxt: the validation context
241 * @node: the context node
242 * @error: the error code
243 * @msg: the error message
244 * @str1: extra data
245 * @str2: extra data
246 * @str3: extra data
247 *
248 * Handle a validation error
249 */
250static void
251xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
252 const char *msg, const xmlChar *str1, const xmlChar *str2,
253 const xmlChar *str3)
254{
255 xmlGenericErrorFunc channel = NULL;
256 void *data = NULL;
257
258 if (ctxt != NULL) {
259 ctxt->nberrors++;
260 ctxt->err = error;
261 channel = ctxt->error;
262 data = ctxt->userData;
263 }
264 /* reajust to global error numbers */
265 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
266 __xmlRaiseError(channel, data, ctxt, node, XML_FROM_SCHEMASP,
267 error, XML_ERR_ERROR, NULL, 0,
268 (const char *) str1, (const char *) str2,
269 (const char *) str3, 0, 0,
270 msg, str1, str2, str3);
271}
272/**
273 * xmlSchemaVErr:
274 * @ctxt: the validation context
275 * @node: the context node
276 * @error: the error code
277 * @msg: the error message
278 * @str1: extra data
279 * @str2: extra data
280 *
281 * Handle a validation error
282 */
283static void
284xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
285 const char *msg, const xmlChar * str1, const xmlChar * str2)
286{
287 xmlGenericErrorFunc channel = NULL;
288 void *data = NULL;
289
290 if (ctxt != NULL) {
291 ctxt->nberrors++;
292 ctxt->err = error;
293 channel = ctxt->error;
294 data = ctxt->userData;
295 }
296 /* reajust to global error numbers */
297 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
298 __xmlRaiseError(channel, data, ctxt, node, XML_FROM_SCHEMASP,
299 error, XML_ERR_ERROR, NULL, 0,
300 (const char *) str1, (const char *) str2, NULL, 0, 0,
301 msg, str1, str2);
302}
Daniel Veillard4255d502002-04-16 15:50:10 +0000303
304/************************************************************************
305 * *
306 * Allocation functions *
307 * *
308 ************************************************************************/
309
310/**
311 * xmlSchemaNewSchema:
312 * @ctxt: a schema validation context (optional)
313 *
314 * Allocate a new Schema structure.
315 *
316 * Returns the newly allocated structure or NULL in case or error
317 */
318static xmlSchemaPtr
319xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
320{
321 xmlSchemaPtr ret;
322
323 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
324 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000325 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000326 return (NULL);
327 }
328 memset(ret, 0, sizeof(xmlSchema));
329
330 return (ret);
331}
332
333/**
334 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000335 *
336 * Allocate a new Facet structure.
337 *
338 * Returns the newly allocated structure or NULL in case or error
339 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000340xmlSchemaFacetPtr
341xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000342{
343 xmlSchemaFacetPtr ret;
344
345 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
346 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000347 return (NULL);
348 }
349 memset(ret, 0, sizeof(xmlSchemaFacet));
350
351 return (ret);
352}
353
354/**
355 * xmlSchemaNewAnnot:
356 * @ctxt: a schema validation context (optional)
357 * @node: a node
358 *
359 * Allocate a new annotation structure.
360 *
361 * Returns the newly allocated structure or NULL in case or error
362 */
363static xmlSchemaAnnotPtr
364xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
365{
366 xmlSchemaAnnotPtr ret;
367
368 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
369 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000370 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000371 return (NULL);
372 }
373 memset(ret, 0, sizeof(xmlSchemaAnnot));
374 ret->content = node;
375 return (ret);
376}
377
378/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000379 * xmlSchemaFreeAnnot:
380 * @annot: a schema type structure
381 *
382 * Deallocate a annotation structure
383 */
384static void
385xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
386{
387 if (annot == NULL)
388 return;
389 xmlFree(annot);
390}
391
392/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000393 * xmlSchemaFreeNotation:
394 * @schema: a schema notation structure
395 *
396 * Deallocate a Schema Notation structure.
397 */
398static void
399xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
400{
401 if (nota == NULL)
402 return;
403 if (nota->name != NULL)
404 xmlFree((xmlChar *) nota->name);
405 xmlFree(nota);
406}
407
408/**
409 * xmlSchemaFreeAttribute:
410 * @schema: a schema attribute structure
411 *
412 * Deallocate a Schema Attribute structure.
413 */
414static void
415xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
416{
417 if (attr == NULL)
418 return;
419 if (attr->name != NULL)
420 xmlFree((xmlChar *) attr->name);
421 if (attr->ref != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000422 xmlFree((xmlChar *) attr->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000423 if (attr->refNs != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000424 xmlFree((xmlChar *) attr->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +0000425 if (attr->typeName != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000426 xmlFree((xmlChar *) attr->typeName);
Daniel Veillard4255d502002-04-16 15:50:10 +0000427 if (attr->typeNs != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000428 xmlFree((xmlChar *) attr->typeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +0000429 xmlFree(attr);
430}
431
432/**
433 * xmlSchemaFreeAttributeGroup:
434 * @schema: a schema attribute group structure
435 *
436 * Deallocate a Schema Attribute Group structure.
437 */
438static void
439xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
440{
441 if (attr == NULL)
442 return;
443 if (attr->name != NULL)
444 xmlFree((xmlChar *) attr->name);
Daniel Veillard91a13252003-03-27 23:44:43 +0000445 if (attr->ref != NULL)
446 xmlFree((xmlChar *) attr->ref);
447 if (attr->refNs != NULL)
448 xmlFree((xmlChar *) attr->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +0000449 xmlFree(attr);
450}
451
452/**
453 * xmlSchemaFreeElement:
454 * @schema: a schema element structure
455 *
456 * Deallocate a Schema Element structure.
457 */
458static void
459xmlSchemaFreeElement(xmlSchemaElementPtr elem)
460{
461 if (elem == NULL)
462 return;
463 if (elem->name != NULL)
464 xmlFree((xmlChar *) elem->name);
465 if (elem->namedType != NULL)
466 xmlFree((xmlChar *) elem->namedType);
467 if (elem->namedTypeNs != NULL)
468 xmlFree((xmlChar *) elem->namedTypeNs);
469 if (elem->ref != NULL)
470 xmlFree((xmlChar *) elem->ref);
471 if (elem->refNs != NULL)
472 xmlFree((xmlChar *) elem->refNs);
Daniel Veillard32370232002-10-16 14:08:14 +0000473 if (elem->annot != NULL)
474 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000475 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000476 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000477 xmlFree(elem);
478}
479
480/**
481 * xmlSchemaFreeFacet:
482 * @facet: a schema facet structure
483 *
484 * Deallocate a Schema Facet structure.
485 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000486void
Daniel Veillard4255d502002-04-16 15:50:10 +0000487xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
488{
489 if (facet == NULL)
490 return;
491 if (facet->value != NULL)
492 xmlFree((xmlChar *) facet->value);
493 if (facet->id != NULL)
494 xmlFree((xmlChar *) facet->id);
495 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000496 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000497 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000498 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000499 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000500 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000501 xmlFree(facet);
502}
503
504/**
505 * xmlSchemaFreeType:
506 * @type: a schema type structure
507 *
508 * Deallocate a Schema Type structure.
509 */
510void
511xmlSchemaFreeType(xmlSchemaTypePtr type)
512{
513 if (type == NULL)
514 return;
515 if (type->name != NULL)
516 xmlFree((xmlChar *) type->name);
517 if (type->base != NULL)
518 xmlFree((xmlChar *) type->base);
519 if (type->baseNs != NULL)
520 xmlFree((xmlChar *) type->baseNs);
521 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000522 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000523 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000524 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000525
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000526 facet = type->facets;
527 while (facet != NULL) {
528 next = facet->next;
529 xmlSchemaFreeFacet(facet);
530 facet = next;
531 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000532 }
533 xmlFree(type);
534}
535
536/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000537 * xmlSchemaFree:
538 * @schema: a schema structure
539 *
540 * Deallocate a Schema structure.
541 */
542void
543xmlSchemaFree(xmlSchemaPtr schema)
544{
545 if (schema == NULL)
546 return;
547
Daniel Veillard91a13252003-03-27 23:44:43 +0000548 if (schema->id != NULL)
549 xmlFree((xmlChar *) schema->id);
550 if (schema->targetNamespace != NULL)
551 xmlFree((xmlChar *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000552 if (schema->name != NULL)
553 xmlFree((xmlChar *) schema->name);
554 if (schema->notaDecl != NULL)
555 xmlHashFree(schema->notaDecl,
556 (xmlHashDeallocator) xmlSchemaFreeNotation);
557 if (schema->attrDecl != NULL)
558 xmlHashFree(schema->attrDecl,
559 (xmlHashDeallocator) xmlSchemaFreeAttribute);
560 if (schema->attrgrpDecl != NULL)
561 xmlHashFree(schema->attrgrpDecl,
562 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
563 if (schema->elemDecl != NULL)
564 xmlHashFree(schema->elemDecl,
565 (xmlHashDeallocator) xmlSchemaFreeElement);
566 if (schema->typeDecl != NULL)
567 xmlHashFree(schema->typeDecl,
568 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000569 if (schema->groupDecl != NULL)
570 xmlHashFree(schema->groupDecl,
571 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard4255d502002-04-16 15:50:10 +0000572 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000573 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000574 if (schema->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000575 xmlFreeDoc(schema->doc);
Daniel Veillard4255d502002-04-16 15:50:10 +0000576
577 xmlFree(schema);
578}
579
580/************************************************************************
581 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000582 * Debug functions *
583 * *
584 ************************************************************************/
585
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000586#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000587
Daniel Veillard4255d502002-04-16 15:50:10 +0000588/**
589 * xmlSchemaElementDump:
590 * @elem: an element
591 * @output: the file output
592 *
593 * Dump the element
594 */
595static void
596xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000597 const xmlChar * name ATTRIBUTE_UNUSED,
598 const xmlChar * context ATTRIBUTE_UNUSED,
599 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000600{
601 if (elem == NULL)
602 return;
603
604 fprintf(output, "Element ");
605 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000606 fprintf(output, "toplevel ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000607 fprintf(output, ": %s ", elem->name);
608 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000609 fprintf(output, "namespace '%s' ", namespace);
610
Daniel Veillard4255d502002-04-16 15:50:10 +0000611 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000612 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000613 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000614 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000615 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000616 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000617 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000618 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000619 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000620 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000621 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000623 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000624 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000625 fprintf(output, "\n");
626 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000627 fprintf(output, " ");
628 if (elem->minOccurs != 1)
629 fprintf(output, "min: %d ", elem->minOccurs);
630 if (elem->maxOccurs >= UNBOUNDED)
631 fprintf(output, "max: unbounded\n");
632 else if (elem->maxOccurs != 1)
633 fprintf(output, "max: %d\n", elem->maxOccurs);
634 else
635 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000636 }
637 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000638 fprintf(output, " type: %s", elem->namedType);
639 if (elem->namedTypeNs != NULL)
640 fprintf(output, " ns %s\n", elem->namedTypeNs);
641 else
642 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000643 }
644 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000645 fprintf(output, " substitutionGroup: %s", elem->substGroup);
646 if (elem->substGroupNs != NULL)
647 fprintf(output, " ns %s\n", elem->substGroupNs);
648 else
649 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000650 }
651 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000652 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000653}
654
655/**
656 * xmlSchemaAnnotDump:
657 * @output: the file output
658 * @annot: a annotation
659 *
660 * Dump the annotation
661 */
662static void
663xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
664{
665 xmlChar *content;
666
667 if (annot == NULL)
668 return;
669
670 content = xmlNodeGetContent(annot->content);
671 if (content != NULL) {
672 fprintf(output, " Annot: %s\n", content);
673 xmlFree(content);
674 } else
675 fprintf(output, " Annot: empty\n");
676}
677
678/**
679 * xmlSchemaTypeDump:
680 * @output: the file output
681 * @type: a type structure
682 *
683 * Dump a SchemaType structure
684 */
685static void
686xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
687{
688 if (type == NULL) {
689 fprintf(output, "Type: NULL\n");
690 return;
691 }
692 fprintf(output, "Type: ");
693 if (type->name != NULL)
694 fprintf(output, "%s, ", type->name);
695 else
696 fprintf(output, "no name");
697 switch (type->type) {
698 case XML_SCHEMA_TYPE_BASIC:
699 fprintf(output, "basic ");
700 break;
701 case XML_SCHEMA_TYPE_SIMPLE:
702 fprintf(output, "simple ");
703 break;
704 case XML_SCHEMA_TYPE_COMPLEX:
705 fprintf(output, "complex ");
706 break;
707 case XML_SCHEMA_TYPE_SEQUENCE:
708 fprintf(output, "sequence ");
709 break;
710 case XML_SCHEMA_TYPE_CHOICE:
711 fprintf(output, "choice ");
712 break;
713 case XML_SCHEMA_TYPE_ALL:
714 fprintf(output, "all ");
715 break;
716 case XML_SCHEMA_TYPE_UR:
717 fprintf(output, "ur ");
718 break;
719 case XML_SCHEMA_TYPE_RESTRICTION:
720 fprintf(output, "restriction ");
721 break;
722 case XML_SCHEMA_TYPE_EXTENSION:
723 fprintf(output, "extension ");
724 break;
725 default:
726 fprintf(output, "unknowntype%d ", type->type);
727 break;
728 }
729 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000730 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000731 }
732 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000733 case XML_SCHEMA_CONTENT_UNKNOWN:
734 fprintf(output, "unknown ");
735 break;
736 case XML_SCHEMA_CONTENT_EMPTY:
737 fprintf(output, "empty ");
738 break;
739 case XML_SCHEMA_CONTENT_ELEMENTS:
740 fprintf(output, "element ");
741 break;
742 case XML_SCHEMA_CONTENT_MIXED:
743 fprintf(output, "mixed ");
744 break;
745 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
746 fprintf(output, "mixed_or_elems ");
747 break;
748 case XML_SCHEMA_CONTENT_BASIC:
749 fprintf(output, "basic ");
750 break;
751 case XML_SCHEMA_CONTENT_SIMPLE:
752 fprintf(output, "simple ");
753 break;
754 case XML_SCHEMA_CONTENT_ANY:
755 fprintf(output, "any ");
756 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000757 }
758 fprintf(output, "\n");
759 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000760 fprintf(output, " ");
761 if (type->minOccurs != 1)
762 fprintf(output, "min: %d ", type->minOccurs);
763 if (type->maxOccurs >= UNBOUNDED)
764 fprintf(output, "max: unbounded\n");
765 else if (type->maxOccurs != 1)
766 fprintf(output, "max: %d\n", type->maxOccurs);
767 else
768 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000769 }
770 if (type->annot != NULL)
771 xmlSchemaAnnotDump(output, type->annot);
772 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000773 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000774
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000775 fprintf(output, " subtypes: ");
776 while (sub != NULL) {
777 fprintf(output, "%s ", sub->name);
778 sub = sub->next;
779 }
780 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000781 }
782
783}
784
785/**
786 * xmlSchemaDump:
787 * @output: the file output
788 * @schema: a schema structure
789 *
790 * Dump a Schema structure.
791 */
792void
793xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
794{
795 if (schema == NULL) {
796 fprintf(output, "Schemas: NULL\n");
797 return;
798 }
799 fprintf(output, "Schemas: ");
800 if (schema->name != NULL)
801 fprintf(output, "%s, ", schema->name);
802 else
803 fprintf(output, "no name, ");
804 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +0000805 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000806 else
807 fprintf(output, "no target namespace");
808 fprintf(output, "\n");
809 if (schema->annot != NULL)
810 xmlSchemaAnnotDump(output, schema->annot);
811
812 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
813 output);
814 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000815 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +0000816}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000817#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +0000818
819/************************************************************************
820 * *
821 * Parsing functions *
822 * *
823 ************************************************************************/
824
825/**
826 * xmlSchemaGetType:
827 * @schema: the schemas context
828 * @name: the type name
829 * @ns: the type namespace
830 *
831 * Lookup a type in the schemas or the predefined types
832 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000833 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +0000834 */
835static xmlSchemaTypePtr
836xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000837 const xmlChar * namespace)
838{
Daniel Veillard4255d502002-04-16 15:50:10 +0000839 xmlSchemaTypePtr ret;
840
841 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000842 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000843 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000844 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
845 if (ret != NULL)
846 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +0000847 }
848 ret = xmlSchemaGetPredefinedType(name, namespace);
849#ifdef DEBUG
850 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000851 if (namespace == NULL)
852 fprintf(stderr, "Unable to lookup type %s", name);
853 else
854 fprintf(stderr, "Unable to lookup type %s:%s", name,
855 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000856 }
857#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000858 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +0000859}
860
861/************************************************************************
862 * *
863 * Parsing functions *
864 * *
865 ************************************************************************/
866
867#define IS_BLANK_NODE(n) \
868 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
869
870/**
871 * xmlSchemaIsBlank:
872 * @str: a string
873 *
874 * Check if a string is ignorable
875 *
876 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
877 */
878static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000879xmlSchemaIsBlank(xmlChar * str)
880{
Daniel Veillard4255d502002-04-16 15:50:10 +0000881 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000882 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +0000883 while (*str != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000884 if (!(IS_BLANK(*str)))
885 return (0);
886 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +0000887 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000888 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +0000889}
890
891/**
892 * xmlSchemaAddNotation:
893 * @ctxt: a schema validation context
894 * @schema: the schema being built
895 * @name: the item name
896 *
897 * Add an XML schema Attrribute declaration
898 * *WARNING* this interface is highly subject to change
899 *
900 * Returns the new struture or NULL in case of error
901 */
902static xmlSchemaNotationPtr
903xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000904 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +0000905{
906 xmlSchemaNotationPtr ret = NULL;
907 int val;
908
909 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
910 return (NULL);
911
912 if (schema->notaDecl == NULL)
913 schema->notaDecl = xmlHashCreate(10);
914 if (schema->notaDecl == NULL)
915 return (NULL);
916
917 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
918 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000919 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000920 return (NULL);
921 }
922 memset(ret, 0, sizeof(xmlSchemaNotation));
923 ret->name = xmlStrdup(name);
924 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
925 ret);
926 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000927 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
928 XML_SCHEMAP_REDEFINED_NOTATION,
929 "Notation %s already defined\n",
930 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000931 xmlFree((char *) ret->name);
932 xmlFree(ret);
933 return (NULL);
934 }
935 return (ret);
936}
937
938
939/**
940 * xmlSchemaAddAttribute:
941 * @ctxt: a schema validation context
942 * @schema: the schema being built
943 * @name: the item name
944 * @container: the container's name
945 *
946 * Add an XML schema Attrribute declaration
947 * *WARNING* this interface is highly subject to change
948 *
949 * Returns the new struture or NULL in case of error
950 */
951static xmlSchemaAttributePtr
952xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
953 const xmlChar * name)
954{
955 xmlSchemaAttributePtr ret = NULL;
956 int val;
957
958 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
959 return (NULL);
960
961 if (schema->attrDecl == NULL)
962 schema->attrDecl = xmlHashCreate(10);
963 if (schema->attrDecl == NULL)
964 return (NULL);
965
966 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
967 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000968 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000969 return (NULL);
970 }
971 memset(ret, 0, sizeof(xmlSchemaAttribute));
972 ret->name = xmlStrdup(name);
973 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000974 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +0000975 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000976 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
977 XML_SCHEMAP_REDEFINED_ATTR,
978 "Attribute %s already defined\n",
979 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000980 xmlFree((char *) ret->name);
981 xmlFree(ret);
982 return (NULL);
983 }
984 return (ret);
985}
986
987/**
988 * xmlSchemaAddAttributeGroup:
989 * @ctxt: a schema validation context
990 * @schema: the schema being built
991 * @name: the item name
992 *
993 * Add an XML schema Attrribute Group declaration
994 *
995 * Returns the new struture or NULL in case of error
996 */
997static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000998xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
999 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001000{
1001 xmlSchemaAttributeGroupPtr ret = NULL;
1002 int val;
1003
1004 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1005 return (NULL);
1006
1007 if (schema->attrgrpDecl == NULL)
1008 schema->attrgrpDecl = xmlHashCreate(10);
1009 if (schema->attrgrpDecl == NULL)
1010 return (NULL);
1011
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001012 ret =
1013 (xmlSchemaAttributeGroupPtr)
1014 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001015 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001016 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001017 return (NULL);
1018 }
1019 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
1020 ret->name = xmlStrdup(name);
1021 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001022 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001023 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001024 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1025 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1026 "Attribute group %s already defined\n",
1027 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001028 xmlFree((char *) ret->name);
1029 xmlFree(ret);
1030 return (NULL);
1031 }
1032 return (ret);
1033}
1034
1035/**
1036 * xmlSchemaAddElement:
1037 * @ctxt: a schema validation context
1038 * @schema: the schema being built
1039 * @name: the type name
1040 * @namespace: the type namespace
1041 *
1042 * Add an XML schema Element declaration
1043 * *WARNING* this interface is highly subject to change
1044 *
1045 * Returns the new struture or NULL in case of error
1046 */
1047static xmlSchemaElementPtr
1048xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1049 const xmlChar * name, const xmlChar * namespace)
1050{
1051 xmlSchemaElementPtr ret = NULL;
1052 int val;
1053
1054 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1055 return (NULL);
1056
1057 if (schema->elemDecl == NULL)
1058 schema->elemDecl = xmlHashCreate(10);
1059 if (schema->elemDecl == NULL)
1060 return (NULL);
1061
1062 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1063 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001064 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001065 return (NULL);
1066 }
1067 memset(ret, 0, sizeof(xmlSchemaElement));
1068 ret->name = xmlStrdup(name);
1069 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001070 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001071 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001072 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001073
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001074 snprintf(buf, 99, "privatieelem%d", ctxt->counter++ + 1);
1075 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1076 namespace, ret);
1077 if (val != 0) {
1078 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1079 XML_SCHEMAP_REDEFINED_ELEMENT,
1080 "Element %s already defined\n",
1081 name, NULL);
1082 xmlFree((char *) ret->name);
1083 xmlFree(ret);
1084 return (NULL);
1085 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001086 }
1087 return (ret);
1088}
1089
1090/**
1091 * xmlSchemaAddType:
1092 * @ctxt: a schema validation context
1093 * @schema: the schema being built
1094 * @name: the item name
1095 *
1096 * Add an XML schema Simple Type definition
1097 * *WARNING* this interface is highly subject to change
1098 *
1099 * Returns the new struture or NULL in case of error
1100 */
1101static xmlSchemaTypePtr
1102xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1103 const xmlChar * name)
1104{
1105 xmlSchemaTypePtr ret = NULL;
1106 int val;
1107
1108 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1109 return (NULL);
1110
1111 if (schema->typeDecl == NULL)
1112 schema->typeDecl = xmlHashCreate(10);
1113 if (schema->typeDecl == NULL)
1114 return (NULL);
1115
1116 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1117 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001118 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001119 return (NULL);
1120 }
1121 memset(ret, 0, sizeof(xmlSchemaType));
1122 ret->name = xmlStrdup(name);
1123 val = xmlHashAddEntry2(schema->typeDecl, name, schema->targetNamespace,
1124 ret);
1125 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001126 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1127 XML_SCHEMAP_REDEFINED_TYPE,
1128 "Type %s already defined\n",
1129 name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001130 xmlFree((char *) ret->name);
1131 xmlFree(ret);
1132 return (NULL);
1133 }
1134 ret->minOccurs = 1;
1135 ret->maxOccurs = 1;
1136
1137 return (ret);
1138}
1139
1140/**
1141 * xmlSchemaAddGroup:
1142 * @ctxt: a schema validation context
1143 * @schema: the schema being built
1144 * @name: the group name
1145 *
1146 * Add an XML schema Group definition
1147 *
1148 * Returns the new struture or NULL in case of error
1149 */
1150static xmlSchemaTypePtr
1151xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001152 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001153{
1154 xmlSchemaTypePtr ret = NULL;
1155 int val;
1156
1157 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1158 return (NULL);
1159
1160 if (schema->groupDecl == NULL)
1161 schema->groupDecl = xmlHashCreate(10);
1162 if (schema->groupDecl == NULL)
1163 return (NULL);
1164
1165 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1166 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001167 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001168 return (NULL);
1169 }
1170 memset(ret, 0, sizeof(xmlSchemaType));
1171 ret->name = xmlStrdup(name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001172 val =
1173 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1174 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001175 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001176 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1177 XML_SCHEMAP_REDEFINED_GROUP,
1178 "Group %s already defined\n",
1179 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001180 xmlFree((char *) ret->name);
1181 xmlFree(ret);
1182 return (NULL);
1183 }
1184 ret->minOccurs = 1;
1185 ret->maxOccurs = 1;
1186
1187 return (ret);
1188}
1189
1190/************************************************************************
1191 * *
1192 * Utilities for parsing *
1193 * *
1194 ************************************************************************/
1195
1196/**
1197 * xmlGetQNameProp:
1198 * @ctxt: a schema validation context
1199 * @node: a subtree containing XML Schema informations
1200 * @name: the attribute name
1201 * @namespace: the result namespace if any
1202 *
1203 * Extract a QName Attribute value
1204 *
1205 * Returns the NCName or NULL if not found, and also update @namespace
1206 * with the namespace URI
1207 */
1208static xmlChar *
1209xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001210 const char *name, xmlChar ** namespace)
1211{
Daniel Veillard4255d502002-04-16 15:50:10 +00001212 xmlChar *val, *ret, *prefix;
1213 xmlNsPtr ns;
1214
1215
1216 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001217 *namespace = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00001218 val = xmlGetProp(node, (const xmlChar *) name);
1219 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001220 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001221
1222 ret = xmlSplitQName2(val, &prefix);
1223 if (ret == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001224 return (val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001225 xmlFree(val);
1226
1227 ns = xmlSearchNs(node->doc, node, prefix);
1228 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001229 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1230 "Attribute %s: the QName prefix %s is undefined\n",
1231 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001232 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001233 *namespace = xmlStrdup(ns->href);
Daniel Veillard4255d502002-04-16 15:50:10 +00001234 }
1235 xmlFree(prefix);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001236 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001237}
1238
1239/**
1240 * xmlGetMaxOccurs:
1241 * @ctxt: a schema validation context
1242 * @node: a subtree containing XML Schema informations
1243 *
1244 * Get the maxOccurs property
1245 *
1246 * Returns the default if not found, or the value
1247 */
1248static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001249xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1250{
Daniel Veillard4255d502002-04-16 15:50:10 +00001251 xmlChar *val, *cur;
1252 int ret = 0;
1253
1254 val = xmlGetProp(node, (const xmlChar *) "maxOccurs");
1255 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001256 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001257
1258 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001259 xmlFree(val);
1260 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001261 }
1262
1263 cur = val;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001264 while (IS_BLANK(*cur))
1265 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001266 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001267 ret = ret * 10 + (*cur - '0');
1268 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001269 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001270 while (IS_BLANK(*cur))
1271 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001272 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001273 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1274 "invalid value for maxOccurs: %s\n", val, NULL);
1275 xmlFree(val);
1276 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001277 }
1278 xmlFree(val);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001279 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001280}
1281
1282/**
1283 * xmlGetMinOccurs:
1284 * @ctxt: a schema validation context
1285 * @node: a subtree containing XML Schema informations
1286 *
1287 * Get the minOccurs property
1288 *
1289 * Returns the default if not found, or the value
1290 */
1291static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001292xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1293{
Daniel Veillard4255d502002-04-16 15:50:10 +00001294 xmlChar *val, *cur;
1295 int ret = 0;
1296
1297 val = xmlGetProp(node, (const xmlChar *) "minOccurs");
1298 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001299 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001300
1301 cur = val;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001302 while (IS_BLANK(*cur))
1303 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001304 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001305 ret = ret * 10 + (*cur - '0');
1306 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001307 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001308 while (IS_BLANK(*cur))
1309 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001310 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001311 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1312 "invalid value for minOccurs: %s\n", val, NULL);
1313 xmlFree(val);
1314 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001315 }
1316 xmlFree(val);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001317 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001318}
1319
1320/**
1321 * xmlGetBooleanProp:
1322 * @ctxt: a schema validation context
1323 * @node: a subtree containing XML Schema informations
1324 * @name: the attribute name
1325 * @def: the default value
1326 *
1327 * Get is a bolean property is set
1328 *
1329 * Returns the default if not found, 0 if found to be false,
1330 * 1 if found to be true
1331 */
1332static int
1333xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001334 const char *name, int def)
1335{
Daniel Veillard4255d502002-04-16 15:50:10 +00001336 xmlChar *val;
1337
1338 val = xmlGetProp(node, (const xmlChar *) name);
1339 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001340 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001341
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001342 if (xmlStrEqual(val, BAD_CAST "true"))
1343 def = 1;
1344 else if (xmlStrEqual(val, BAD_CAST "false"))
1345 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001346 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001347 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1348 "Attribute %s: the value %s is not boolean\n",
1349 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001350 }
1351 xmlFree(val);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001352 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001353}
1354
1355/************************************************************************
1356 * *
1357 * Shema extraction from an Infoset *
1358 * *
1359 ************************************************************************/
1360static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1361 ctxt, xmlSchemaPtr schema,
1362 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001363static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1364 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001365 xmlSchemaPtr schema,
1366 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001367static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1368 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001369 xmlSchemaPtr schema,
1370 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001371 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001372static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1373 xmlSchemaPtr schema,
1374 xmlNodePtr node);
1375static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1376 xmlSchemaPtr schema,
1377 xmlNodePtr node);
1378static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1379 ctxt,
1380 xmlSchemaPtr schema,
1381 xmlNodePtr node);
1382static xmlSchemaAttributeGroupPtr
1383xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1384 xmlSchemaPtr schema, xmlNodePtr node);
1385static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1386 xmlSchemaPtr schema,
1387 xmlNodePtr node);
1388static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1389 xmlSchemaPtr schema,
1390 xmlNodePtr node);
1391static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001392xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1393 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001394
1395/**
1396 * xmlSchemaParseAttrDecls:
1397 * @ctxt: a schema validation context
1398 * @schema: the schema being built
1399 * @node: a subtree containing XML Schema informations
1400 * @type: the hosting type
1401 *
1402 * parse a XML schema attrDecls declaration corresponding to
1403 * <!ENTITY % attrDecls
1404 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1405 */
1406static xmlNodePtr
1407xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1408 xmlNodePtr child, xmlSchemaTypePtr type)
1409{
1410 xmlSchemaAttributePtr lastattr, attr;
1411
1412 lastattr = NULL;
1413 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001414 (IS_SCHEMA(child, "attributeGroup"))) {
1415 attr = NULL;
1416 if (IS_SCHEMA(child, "attribute")) {
1417 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1418 } else if (IS_SCHEMA(child, "attributeGroup")) {
1419 attr = (xmlSchemaAttributePtr)
1420 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1421 }
1422 if (attr != NULL) {
1423 if (lastattr == NULL) {
1424 type->attributes = attr;
1425 lastattr = attr;
1426 } else {
1427 lastattr->next = attr;
1428 lastattr = attr;
1429 }
1430 }
1431 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001432 }
1433 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001434 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1435 if (attr != NULL) {
1436 if (lastattr == NULL) {
1437 type->attributes = attr;
1438 lastattr = attr;
1439 } else {
1440 lastattr->next = attr;
1441 lastattr = attr;
1442 }
1443 }
1444 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001445 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001446 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001447}
1448
1449/**
1450 * xmlSchemaParseAnnotation:
1451 * @ctxt: a schema validation context
1452 * @schema: the schema being built
1453 * @node: a subtree containing XML Schema informations
1454 *
1455 * parse a XML schema Attrribute declaration
1456 * *WARNING* this interface is highly subject to change
1457 *
1458 * Returns -1 in case of error, 0 if the declaration is inproper and
1459 * 1 in case of success.
1460 */
1461static xmlSchemaAnnotPtr
1462xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1463 xmlNodePtr node)
1464{
1465 xmlSchemaAnnotPtr ret;
1466
1467 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1468 return (NULL);
1469 ret = xmlSchemaNewAnnot(ctxt, node);
1470
1471 return (ret);
1472}
1473
1474/**
1475 * xmlSchemaParseFacet:
1476 * @ctxt: a schema validation context
1477 * @schema: the schema being built
1478 * @node: a subtree containing XML Schema informations
1479 *
1480 * parse a XML schema Facet declaration
1481 * *WARNING* this interface is highly subject to change
1482 *
1483 * Returns the new type structure or NULL in case of error
1484 */
1485static xmlSchemaFacetPtr
1486xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001487 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001488{
1489 xmlSchemaFacetPtr facet;
1490 xmlNodePtr child = NULL;
1491 xmlChar *value;
1492
1493 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1494 return (NULL);
1495
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001496 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001497 if (facet == NULL) {
1498 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1499 return (NULL);
1500 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001501 facet->node = node;
1502 value = xmlGetProp(node, (const xmlChar *) "value");
1503 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001504 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1505 "Facet %s has no value\n", node->name, NULL);
1506 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001507 return (NULL);
1508 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001509 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001510 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001511 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001512 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001513 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001514 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001515 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001516 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001517 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001518 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001519 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001520 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001521 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001522 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001523 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001524 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001525 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001526 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001527 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001528 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001529 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001530 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1531 } else if (IS_SCHEMA(node, "minLength")) {
1532 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1533 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001534 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1535 "Unknown facet type %s\n", node->name, NULL);
1536 xmlSchemaFreeFacet(facet);
1537 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001538 }
1539 facet->id = xmlGetProp(node, (const xmlChar *) "id");
1540 facet->value = value;
1541 child = node->children;
1542
1543 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001544 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1545 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001546 }
1547 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001548 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1549 "Facet %s has unexpected child content\n",
1550 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001551 }
1552 return (facet);
1553}
1554
1555/**
1556 * xmlSchemaParseAny:
1557 * @ctxt: a schema validation context
1558 * @schema: the schema being built
1559 * @node: a subtree containing XML Schema informations
1560 *
1561 * parse a XML schema Any declaration
1562 * *WARNING* this interface is highly subject to change
1563 *
1564 * Returns the new type structure or NULL in case of error
1565 */
1566static xmlSchemaTypePtr
1567xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1568 xmlNodePtr node)
1569{
1570 xmlSchemaTypePtr type;
1571 xmlNodePtr child = NULL;
1572 xmlChar name[30];
1573
1574 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1575 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001576 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001577 type = xmlSchemaAddType(ctxt, schema, name);
1578 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001579 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001580 type->node = node;
1581 type->type = XML_SCHEMA_TYPE_ANY;
1582 child = node->children;
1583 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1584 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1585
1586 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001587 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1588 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001589 }
1590 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001591 xmlSchemaPErr2(ctxt, node, child,
1592 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1593 "Sequence %s has unexpected content\n", type->name,
1594 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001595 }
1596
1597 return (type);
1598}
1599
1600/**
1601 * xmlSchemaParseNotation:
1602 * @ctxt: a schema validation context
1603 * @schema: the schema being built
1604 * @node: a subtree containing XML Schema informations
1605 *
1606 * parse a XML schema Notation declaration
1607 *
1608 * Returns the new structure or NULL in case of error
1609 */
1610static xmlSchemaNotationPtr
1611xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001612 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001613{
1614 xmlChar *name;
1615 xmlSchemaNotationPtr ret;
1616 xmlNodePtr child = NULL;
1617
1618 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1619 return (NULL);
1620 name = xmlGetProp(node, (const xmlChar *) "name");
1621 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001622 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1623 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001624 return (NULL);
1625 }
1626 ret = xmlSchemaAddNotation(ctxt, schema, name);
1627 if (ret == NULL) {
1628 xmlFree(name);
1629 return (NULL);
1630 }
1631 child = node->children;
1632 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001633 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1634 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001635 }
1636 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001637 xmlSchemaPErr2(ctxt, node, child,
1638 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1639 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001640 }
1641
1642 return (ret);
1643}
1644
1645/**
1646 * xmlSchemaParseAnyAttribute:
1647 * @ctxt: a schema validation context
1648 * @schema: the schema being built
1649 * @node: a subtree containing XML Schema informations
1650 *
1651 * parse a XML schema AnyAttrribute declaration
1652 * *WARNING* this interface is highly subject to change
1653 *
1654 * Returns an attribute def structure or NULL
1655 */
1656static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001657xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1658 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001659{
1660 xmlChar *processContents;
1661 xmlSchemaAttributePtr ret;
1662 xmlNodePtr child = NULL;
1663 char name[100];
1664
1665 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1666 return (NULL);
1667
1668 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001669 ret = xmlSchemaAddAttribute(ctxt, schema, (xmlChar *) name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001670 if (ret == NULL) {
1671 return (NULL);
1672 }
1673 ret->id = xmlGetProp(node, (const xmlChar *) "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001674 processContents =
1675 xmlGetProp(node, (const xmlChar *) "processContents");
1676 if ((processContents == NULL)
1677 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1678 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1679 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1680 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1681 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1682 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001683 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001684 xmlSchemaPErr2(ctxt, node, child,
1685 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
1686 "anyAttribute has unexpected content for processContents: %s\n",
1687 processContents, NULL);
1688 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001689 }
1690 if (processContents != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001691 xmlFree(processContents);
Daniel Veillard4255d502002-04-16 15:50:10 +00001692
1693 child = node->children;
1694 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001695 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1696 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001697 }
1698 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001699 xmlSchemaPErr2(ctxt, node, child,
1700 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
1701 "anyAttribute %s has unexpected content\n",
1702 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001703 }
1704
1705 return (ret);
1706}
1707
1708
1709/**
1710 * xmlSchemaParseAttribute:
1711 * @ctxt: a schema validation context
1712 * @schema: the schema being built
1713 * @node: a subtree containing XML Schema informations
1714 *
1715 * parse a XML schema Attrribute declaration
1716 * *WARNING* this interface is highly subject to change
1717 *
1718 * Returns -1 in case of error, 0 if the declaration is inproper and
1719 * 1 in case of success.
1720 */
1721static xmlSchemaAttributePtr
1722xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1723 xmlNodePtr node)
1724{
1725 xmlChar *name, *refNs = NULL, *ref = NULL;
1726 xmlSchemaAttributePtr ret;
1727 xmlNodePtr child = NULL;
1728
1729 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1730 return (NULL);
1731 name = xmlGetProp(node, (const xmlChar *) "name");
1732 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001733 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001734
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001735 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1736 if (ref == NULL) {
1737 xmlSchemaPErr2(ctxt, node, child,
1738 XML_SCHEMAP_ATTR_NONAME_NOREF,
1739 "Attribute has no name nor ref\n", NULL, NULL);
1740 return (NULL);
1741 }
1742 snprintf(buf, 99, "anonattr%d", ctxt->counter++ + 1);
1743 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00001744 }
1745 ret = xmlSchemaAddAttribute(ctxt, schema, name);
1746 if (ret == NULL) {
1747 xmlFree(name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001748 if (ref != NULL)
1749 xmlFree(ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001750 return (NULL);
1751 }
1752 xmlFree(name);
1753 ret->ref = ref;
1754 ret->refNs = refNs;
1755 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00001756 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001757 child = node->children;
1758 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001759 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1760 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001761 }
1762 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001763 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1764 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001765 }
1766 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001767 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
1768 "attribute %s has unexpected content\n", name,
1769 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001770 }
1771
1772 return (ret);
1773}
1774
1775/**
1776 * xmlSchemaParseAttributeGroup:
1777 * @ctxt: a schema validation context
1778 * @schema: the schema being built
1779 * @node: a subtree containing XML Schema informations
1780 *
1781 * parse a XML schema Attribute Group declaration
1782 * *WARNING* this interface is highly subject to change
1783 *
1784 * Returns the attribute group or NULL in case of error.
1785 */
1786static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001787xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1788 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001789{
1790 xmlChar *name, *refNs = NULL, *ref = NULL;
1791 xmlSchemaAttributeGroupPtr ret;
1792 xmlSchemaAttributePtr last = NULL, attr;
1793 xmlNodePtr child = NULL;
1794 xmlChar *oldcontainer;
1795
1796 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1797 return (NULL);
1798 oldcontainer = ctxt->container;
1799 name = xmlGetProp(node, (const xmlChar *) "name");
1800 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001801 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001802
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001803 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1804 if (ref == NULL) {
1805 xmlSchemaPErr2(ctxt, node, child,
1806 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
1807 "AttributeGroup has no name nor ref\n", NULL,
1808 NULL);
1809 return (NULL);
1810 }
1811 snprintf(buf, 99, "anonattrgroup%d", ctxt->counter++ + 1);
1812 name = xmlStrdup((xmlChar *) buf);
1813 if (name == NULL) {
1814 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
1815 return (NULL);
1816 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001817 }
1818 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
1819 if (ret == NULL) {
1820 xmlFree(name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001821 if (ref != NULL)
1822 xmlFree(ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001823 return (NULL);
1824 }
1825 ret->ref = ref;
1826 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00001827 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00001828 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001829 child = node->children;
1830 ctxt->container = name;
1831 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001832 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1833 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001834 }
1835 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001836 (IS_SCHEMA(child, "attributeGroup"))) {
1837 attr = NULL;
1838 if (IS_SCHEMA(child, "attribute")) {
1839 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1840 } else if (IS_SCHEMA(child, "attributeGroup")) {
1841 attr = (xmlSchemaAttributePtr)
1842 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1843 }
1844 if (attr != NULL) {
1845 if (last == NULL) {
1846 ret->attributes = attr;
1847 last = attr;
1848 } else {
1849 last->next = attr;
1850 last = attr;
1851 }
1852 }
1853 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001854 }
1855 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001856 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001857 }
1858 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001859 xmlSchemaPErr2(ctxt, node, child,
1860 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
1861 "attribute group %s has unexpected content\n", name,
1862 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001863 }
1864
1865 ctxt->container = oldcontainer;
Daniel Veillard91a13252003-03-27 23:44:43 +00001866 xmlFree(name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001867 return (ret);
1868}
1869
1870/**
1871 * xmlSchemaParseElement:
1872 * @ctxt: a schema validation context
1873 * @schema: the schema being built
1874 * @node: a subtree containing XML Schema informations
1875 *
1876 * parse a XML schema Element declaration
1877 * *WARNING* this interface is highly subject to change
1878 *
1879 * Returns -1 in case of error, 0 if the declaration is inproper and
1880 * 1 in case of success.
1881 */
1882static xmlSchemaElementPtr
1883xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1884 xmlNodePtr node, int toplevel)
1885{
1886 xmlChar *name, *refNs = NULL, *ref = NULL, *namespace, *fixed;
1887 xmlSchemaElementPtr ret;
1888 xmlNodePtr child = NULL;
1889 xmlChar *oldcontainer;
1890
1891 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1892 return (NULL);
1893 oldcontainer = ctxt->container;
1894 name = xmlGetProp(node, (const xmlChar *) "name");
1895 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001896 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001897
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001898 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1899 if (ref == NULL) {
1900 xmlSchemaPErr2(ctxt, node, child,
1901 XML_SCHEMAP_ELEM_NONAME_NOREF,
1902 "Element has no name nor ref\n", NULL, NULL);
1903 return (NULL);
1904 }
1905 snprintf(buf, 99, "anonelem%d", ctxt->counter++ + 1);
1906 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00001907 }
1908 namespace = xmlGetProp(node, (const xmlChar *) "targetNamespace");
1909 if (namespace == NULL)
1910 ret =
1911 xmlSchemaAddElement(ctxt, schema, name,
1912 schema->targetNamespace);
1913 else
1914 ret = xmlSchemaAddElement(ctxt, schema, name, namespace);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001915 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00001916 if (namespace != NULL)
1917 xmlFree(namespace);
1918 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001919 xmlFree(name);
1920 if (ref != NULL)
1921 xmlFree(ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001922 return (NULL);
1923 }
1924 ret->type = XML_SCHEMA_TYPE_ELEMENT;
1925 ret->ref = ref;
1926 ret->refNs = refNs;
1927 if (ref != NULL)
1928 ret->flags |= XML_SCHEMAS_ELEM_REF;
1929 if (toplevel)
1930 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
1931 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
1932 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1933 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
1934 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1935 ctxt->container = name;
1936
1937 ret->id = xmlGetProp(node, BAD_CAST "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001938 ret->namedType =
1939 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
1940 ret->substGroup =
1941 xmlGetQNameProp(ctxt, node, "substitutionGroup",
1942 &(ret->substGroupNs));
Daniel Veillard4255d502002-04-16 15:50:10 +00001943 fixed = xmlGetProp(node, BAD_CAST "fixed");
1944 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
1945 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001946
Daniel Veillard4255d502002-04-16 15:50:10 +00001947 ret->value = xmlGetProp(node, BAD_CAST "default");
1948 if ((ret->value != NULL) && (fixed != NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001949 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
1950 "Element %s has both default and fixed\n",
1951 ret->name, NULL);
1952 xmlFree(fixed);
Daniel Veillard4255d502002-04-16 15:50:10 +00001953 } else if (fixed != NULL) {
1954 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001955 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00001956 }
1957
1958 child = node->children;
1959 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001960 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1961 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001962 }
1963 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001964 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001965 child = child->next;
1966 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001967 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001968 child = child->next;
1969 }
1970 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001971 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
1972 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001973 }
1974 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001975 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
1976 "element %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001977 }
1978
1979 ctxt->container = oldcontainer;
1980 xmlFree(name);
1981 return (ret);
1982}
1983
1984/**
1985 * xmlSchemaParseUnion:
1986 * @ctxt: a schema validation context
1987 * @schema: the schema being built
1988 * @node: a subtree containing XML Schema informations
1989 *
1990 * parse a XML schema Union definition
1991 * *WARNING* this interface is highly subject to change
1992 *
1993 * Returns -1 in case of error, 0 if the declaration is inproper and
1994 * 1 in case of success.
1995 */
1996static xmlSchemaTypePtr
1997xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001998 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001999{
2000 xmlSchemaTypePtr type, subtype, last = NULL;
2001 xmlNodePtr child = NULL;
2002 xmlChar name[30];
2003
2004 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2005 return (NULL);
2006
2007
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002008 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002009 type = xmlSchemaAddType(ctxt, schema, name);
2010 if (type == NULL)
2011 return (NULL);
2012 type->node = node;
2013 type->type = XML_SCHEMA_TYPE_LIST;
2014 type->id = xmlGetProp(node, BAD_CAST "id");
2015 type->ref = xmlGetProp(node, BAD_CAST "memberTypes");
2016
2017 child = node->children;
2018 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002019 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2020 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002021 }
2022 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002023 subtype = (xmlSchemaTypePtr)
2024 xmlSchemaParseSimpleType(ctxt, schema, child);
2025 if (subtype != NULL) {
2026 if (last == NULL) {
2027 type->subtypes = subtype;
2028 last = subtype;
2029 } else {
2030 last->next = subtype;
2031 last = subtype;
2032 }
2033 last->next = NULL;
2034 }
2035 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002036 }
2037 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002038 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2039 "Union %s has unexpected content\n", type->name,
2040 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002041 }
2042 return (type);
2043}
2044
2045/**
2046 * xmlSchemaParseList:
2047 * @ctxt: a schema validation context
2048 * @schema: the schema being built
2049 * @node: a subtree containing XML Schema informations
2050 *
2051 * parse a XML schema List definition
2052 * *WARNING* this interface is highly subject to change
2053 *
2054 * Returns -1 in case of error, 0 if the declaration is inproper and
2055 * 1 in case of success.
2056 */
2057static xmlSchemaTypePtr
2058xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002059 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002060{
2061 xmlSchemaTypePtr type, subtype;
2062 xmlNodePtr child = NULL;
2063 xmlChar name[30];
2064
2065 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2066 return (NULL);
2067
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002068 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002069 type = xmlSchemaAddType(ctxt, schema, name);
2070 if (type == NULL)
2071 return (NULL);
2072 type->node = node;
2073 type->type = XML_SCHEMA_TYPE_LIST;
2074 type->id = xmlGetProp(node, BAD_CAST "id");
2075 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2076
2077 child = node->children;
2078 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002079 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2080 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002081 }
2082 subtype = NULL;
2083 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002084 subtype = (xmlSchemaTypePtr)
2085 xmlSchemaParseSimpleType(ctxt, schema, child);
2086 child = child->next;
2087 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002088 }
2089 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002090 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2091 "List %s has unexpected content\n", type->name,
2092 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002093 }
2094 return (type);
2095}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002096
Daniel Veillard4255d502002-04-16 15:50:10 +00002097/**
2098 * xmlSchemaParseSimpleType:
2099 * @ctxt: a schema validation context
2100 * @schema: the schema being built
2101 * @node: a subtree containing XML Schema informations
2102 *
2103 * parse a XML schema Simple Type definition
2104 * *WARNING* this interface is highly subject to change
2105 *
2106 * Returns -1 in case of error, 0 if the declaration is inproper and
2107 * 1 in case of success.
2108 */
2109static xmlSchemaTypePtr
2110xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2111 xmlNodePtr node)
2112{
2113 xmlSchemaTypePtr type, subtype;
2114 xmlNodePtr child = NULL;
2115 xmlChar *name;
2116
2117 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2118 return (NULL);
2119
2120
2121 name = xmlGetProp(node, (const xmlChar *) "name");
2122 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002123 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002124
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002125 snprintf(buf, 99, "simpletype%d", ctxt->counter++ + 1);
2126 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00002127 }
2128 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002129 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_SIMPLETYPE_NONAME,
2130 "simpleType has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002131 return (NULL);
2132 }
2133 type = xmlSchemaAddType(ctxt, schema, name);
2134 xmlFree(name);
2135 if (type == NULL)
2136 return (NULL);
2137 type->node = node;
2138 type->type = XML_SCHEMA_TYPE_SIMPLE;
2139 type->id = xmlGetProp(node, BAD_CAST "id");
2140
2141 child = node->children;
2142 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002143 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2144 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002145 }
2146 subtype = NULL;
2147 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002148 subtype = (xmlSchemaTypePtr)
2149 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2150 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002151 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002152 subtype = (xmlSchemaTypePtr)
2153 xmlSchemaParseList(ctxt, schema, child);
2154 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002155 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002156 subtype = (xmlSchemaTypePtr)
2157 xmlSchemaParseUnion(ctxt, schema, child);
2158 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002159 }
2160 type->subtypes = subtype;
2161 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002162 xmlSchemaPErr2(ctxt, node, child,
2163 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2164 "SimpleType %s has unexpected content\n",
2165 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002166 }
2167
2168 return (type);
2169}
2170
2171
2172/**
2173 * xmlSchemaParseGroup:
2174 * @ctxt: a schema validation context
2175 * @schema: the schema being built
2176 * @node: a subtree containing XML Schema informations
2177 *
2178 * parse a XML schema Group definition
2179 * *WARNING* this interface is highly subject to change
2180 *
2181 * Returns -1 in case of error, 0 if the declaration is inproper and
2182 * 1 in case of success.
2183 */
2184static xmlSchemaTypePtr
2185xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002186 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002187{
2188 xmlSchemaTypePtr type, subtype;
2189 xmlNodePtr child = NULL;
2190 xmlChar *name, *ref = NULL, *refNs = NULL;
2191
2192 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2193 return (NULL);
2194
2195
2196 name = xmlGetProp(node, (const xmlChar *) "name");
2197 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002198 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002199
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002200 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2201 if (ref == NULL) {
2202 xmlSchemaPErr2(ctxt, node, child,
2203 XML_SCHEMAP_GROUP_NONAME_NOREF,
2204 "Group has no name nor ref\n", NULL, NULL);
2205 return (NULL);
2206 }
2207 snprintf(buf, 99, "anongroup%d", ctxt->counter++ + 1);
2208 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00002209 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002210 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002211 if (type == NULL)
2212 return (NULL);
2213 type->node = node;
2214 type->type = XML_SCHEMA_TYPE_GROUP;
2215 type->id = xmlGetProp(node, BAD_CAST "id");
2216 type->ref = ref;
2217 type->refNs = refNs;
2218 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2219 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2220
2221 child = node->children;
2222 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002223 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2224 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002225 }
2226 subtype = NULL;
2227 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002228 subtype = (xmlSchemaTypePtr)
2229 xmlSchemaParseAll(ctxt, schema, child);
2230 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002231 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002232 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2233 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002234 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002235 subtype = (xmlSchemaTypePtr)
2236 xmlSchemaParseSequence(ctxt, schema, child);
2237 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002238 }
2239 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002240 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002241 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002242 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2243 "Group %s has unexpected content\n", type->name,
2244 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002245 }
2246
2247 return (type);
2248}
2249
2250/**
2251 * xmlSchemaParseAll:
2252 * @ctxt: a schema validation context
2253 * @schema: the schema being built
2254 * @node: a subtree containing XML Schema informations
2255 *
2256 * parse a XML schema All definition
2257 * *WARNING* this interface is highly subject to change
2258 *
2259 * Returns -1 in case of error, 0 if the declaration is inproper and
2260 * 1 in case of success.
2261 */
2262static xmlSchemaTypePtr
2263xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002264 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002265{
2266 xmlSchemaTypePtr type, subtype, last = NULL;
2267 xmlNodePtr child = NULL;
2268 xmlChar name[30];
2269
2270 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2271 return (NULL);
2272
2273
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002274 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002275 type = xmlSchemaAddType(ctxt, schema, name);
2276 if (type == NULL)
2277 return (NULL);
2278 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002279 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002280 type->id = xmlGetProp(node, BAD_CAST "id");
2281 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2282 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2283
2284 child = node->children;
2285 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002286 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2287 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002288 }
2289 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002290 subtype = (xmlSchemaTypePtr)
2291 xmlSchemaParseElement(ctxt, schema, child, 0);
2292 if (subtype != NULL) {
2293 if (last == NULL) {
2294 type->subtypes = subtype;
2295 last = subtype;
2296 } else {
2297 last->next = subtype;
2298 last = subtype;
2299 }
2300 last->next = NULL;
2301 }
2302 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002303 }
2304 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002305 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2306 "All %s has unexpected content\n", type->name,
2307 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002308 }
2309
2310 return (type);
2311}
2312
2313/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002314 * xmlSchemaParseImport:
2315 * @ctxt: a schema validation context
2316 * @schema: the schema being built
2317 * @node: a subtree containing XML Schema informations
2318 *
2319 * parse a XML schema Import definition
2320 * *WARNING* this interface is highly subject to change
2321 *
2322 * Returns -1 in case of error, 0 if the declaration is inproper and
2323 * 1 in case of success.
2324 */
2325static int
2326xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002327 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002328{
2329 xmlNodePtr child = NULL;
2330 xmlChar *namespace;
2331 xmlChar *schemaLocation;
2332 xmlChar *previous;
2333 xmlURIPtr check;
2334
2335 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2336 return (-1);
2337
2338 namespace = xmlGetProp(node, BAD_CAST "namespace");
2339 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002340 check = xmlParseURI((const char *) namespace);
2341 if (check == NULL) {
2342 xmlSchemaPErr2(ctxt, node, child,
2343 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2344 "Import namespace attribute is not an URI: %s\n",
2345 namespace, NULL);
2346 xmlFree(namespace);
2347 return (-1);
2348 } else {
2349 xmlFreeURI(check);
2350 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002351 }
2352 schemaLocation = xmlGetProp(node, BAD_CAST "schemaLocation");
2353 if (schemaLocation != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002354 check = xmlParseURI((const char *) schemaLocation);
2355 if (check == NULL) {
2356 xmlSchemaPErr2(ctxt, node, child,
2357 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2358 "Import schemaLocation attribute is not an URI: %s\n",
2359 schemaLocation, NULL);
2360 if (namespace != NULL)
2361 xmlFree(namespace);
2362 xmlFree(schemaLocation);
2363 return (-1);
2364 } else {
2365 xmlFreeURI(check);
2366 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002367 }
2368 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002369 schema->schemasImports = xmlHashCreate(10);
2370 if (schema->schemasImports == NULL) {
2371 xmlSchemaPErr2(ctxt, node, child,
2372 XML_SCHEMAP_FAILED_BUILD_IMPORT,
2373 "Internal: failed to build import table\n",
2374 NULL, NULL);
2375 if (namespace != NULL)
2376 xmlFree(namespace);
2377 if (schemaLocation != NULL)
2378 xmlFree(schemaLocation);
2379 return (-1);
2380 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002381 }
2382 if (namespace == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002383 previous = xmlHashLookup(schema->schemasImports,
2384 XML_SCHEMAS_DEFAULT_NAMESPACE);
2385 if (schemaLocation != NULL) {
2386 if (previous != NULL) {
2387 if (!xmlStrEqual(schemaLocation, previous)) {
2388 xmlSchemaPErr2(ctxt, node, child,
2389 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2390 "Redefining import for default namespace with a different URI: %s\n",
2391 schemaLocation, NULL);
2392 }
2393 } else {
2394 xmlHashAddEntry(schema->schemasImports,
2395 XML_SCHEMAS_DEFAULT_NAMESPACE,
2396 schemaLocation);
2397 }
2398 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002399 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002400 previous = xmlHashLookup(schema->schemasImports, namespace);
2401 if (schemaLocation != NULL) {
2402 if (previous != NULL) {
2403 if (!xmlStrEqual(schemaLocation, previous)) {
2404 xmlSchemaPErr2(ctxt, node, child,
2405 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2406 "Redefining import for namespace %s with a different URI: %s\n",
2407 namespace, schemaLocation);
2408 }
2409 } else {
2410 xmlHashAddEntry(schema->schemasImports,
2411 namespace, schemaLocation);
2412 }
2413 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002414 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002415
2416 child = node->children;
2417 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002418 /*
2419 * the annotations here are simply discarded ...
2420 */
2421 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00002422 }
2423 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002424 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
2425 "Import has unexpected content\n", NULL, NULL);
2426 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002427 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002428 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002429}
2430
2431/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002432 * xmlSchemaParseChoice:
2433 * @ctxt: a schema validation context
2434 * @schema: the schema being built
2435 * @node: a subtree containing XML Schema informations
2436 *
2437 * parse a XML schema Choice definition
2438 * *WARNING* this interface is highly subject to change
2439 *
2440 * Returns -1 in case of error, 0 if the declaration is inproper and
2441 * 1 in case of success.
2442 */
2443static xmlSchemaTypePtr
2444xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002445 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002446{
2447 xmlSchemaTypePtr type, subtype, last = NULL;
2448 xmlNodePtr child = NULL;
2449 xmlChar name[30];
2450
2451 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2452 return (NULL);
2453
2454
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002455 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002456 type = xmlSchemaAddType(ctxt, schema, name);
2457 if (type == NULL)
2458 return (NULL);
2459 type->node = node;
2460 type->type = XML_SCHEMA_TYPE_CHOICE;
2461 type->id = xmlGetProp(node, BAD_CAST "id");
2462 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2463 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2464
2465 child = node->children;
2466 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002467 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2468 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002469 }
2470 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002471 (IS_SCHEMA(child, "group")) ||
2472 (IS_SCHEMA(child, "any")) ||
2473 (IS_SCHEMA(child, "choice")) ||
2474 (IS_SCHEMA(child, "sequence"))) {
2475 subtype = NULL;
2476 if (IS_SCHEMA(child, "element")) {
2477 subtype = (xmlSchemaTypePtr)
2478 xmlSchemaParseElement(ctxt, schema, child, 0);
2479 } else if (IS_SCHEMA(child, "group")) {
2480 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2481 } else if (IS_SCHEMA(child, "any")) {
2482 subtype = xmlSchemaParseAny(ctxt, schema, child);
2483 } else if (IS_SCHEMA(child, "sequence")) {
2484 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2485 } else if (IS_SCHEMA(child, "choice")) {
2486 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2487 }
2488 if (subtype != NULL) {
2489 if (last == NULL) {
2490 type->subtypes = subtype;
2491 last = subtype;
2492 } else {
2493 last->next = subtype;
2494 last = subtype;
2495 }
2496 last->next = NULL;
2497 }
2498 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002499 }
2500 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002501 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
2502 "Choice %s has unexpected content\n", type->name,
2503 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002504 }
2505
2506 return (type);
2507}
2508
2509/**
2510 * xmlSchemaParseSequence:
2511 * @ctxt: a schema validation context
2512 * @schema: the schema being built
2513 * @node: a subtree containing XML Schema informations
2514 *
2515 * parse a XML schema Sequence definition
2516 * *WARNING* this interface is highly subject to change
2517 *
2518 * Returns -1 in case of error, 0 if the declaration is inproper and
2519 * 1 in case of success.
2520 */
2521static xmlSchemaTypePtr
2522xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002523 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002524{
2525 xmlSchemaTypePtr type, subtype, last = NULL;
2526 xmlNodePtr child = NULL;
2527 xmlChar name[30];
2528
2529 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2530 return (NULL);
2531
2532
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002533 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002534 type = xmlSchemaAddType(ctxt, schema, name);
2535 if (type == NULL)
2536 return (NULL);
2537 type->node = node;
2538 type->type = XML_SCHEMA_TYPE_SEQUENCE;
2539 type->id = xmlGetProp(node, BAD_CAST "id");
2540 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2541 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2542
2543 child = node->children;
2544 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002545 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2546 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002547 }
2548 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002549 (IS_SCHEMA(child, "group")) ||
2550 (IS_SCHEMA(child, "any")) ||
2551 (IS_SCHEMA(child, "choice")) ||
2552 (IS_SCHEMA(child, "sequence"))) {
2553 subtype = NULL;
2554 if (IS_SCHEMA(child, "element")) {
2555 subtype = (xmlSchemaTypePtr)
2556 xmlSchemaParseElement(ctxt, schema, child, 0);
2557 } else if (IS_SCHEMA(child, "group")) {
2558 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2559 } else if (IS_SCHEMA(child, "any")) {
2560 subtype = xmlSchemaParseAny(ctxt, schema, child);
2561 } else if (IS_SCHEMA(child, "choice")) {
2562 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2563 } else if (IS_SCHEMA(child, "sequence")) {
2564 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2565 }
2566 if (subtype != NULL) {
2567 if (last == NULL) {
2568 type->subtypes = subtype;
2569 last = subtype;
2570 } else {
2571 last->next = subtype;
2572 last = subtype;
2573 }
2574 last->next = NULL;
2575 }
2576 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002577 }
2578 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002579 xmlSchemaPErr2(ctxt, node, child,
2580 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
2581 "Sequence %s has unexpected content\n", type->name,
2582 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002583 }
2584
2585 return (type);
2586}
2587
2588/**
2589 * xmlSchemaParseRestriction:
2590 * @ctxt: a schema validation context
2591 * @schema: the schema being built
2592 * @node: a subtree containing XML Schema informations
2593 * @simple: is that part of a simple type.
2594 *
2595 * parse a XML schema Restriction definition
2596 * *WARNING* this interface is highly subject to change
2597 *
2598 * Returns the type definition or NULL in case of error
2599 */
2600static xmlSchemaTypePtr
2601xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2602 xmlNodePtr node, int simple)
2603{
2604 xmlSchemaTypePtr type, subtype;
2605 xmlSchemaFacetPtr facet, lastfacet = NULL;
2606 xmlNodePtr child = NULL;
2607 xmlChar name[30];
2608 xmlChar *oldcontainer;
2609
2610 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2611 return (NULL);
2612
2613 oldcontainer = ctxt->container;
2614
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002615 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002616 type = xmlSchemaAddType(ctxt, schema, name);
2617 if (type == NULL)
2618 return (NULL);
2619 type->node = node;
2620 type->type = XML_SCHEMA_TYPE_RESTRICTION;
2621 type->id = xmlGetProp(node, BAD_CAST "id");
2622 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2623 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002624 xmlSchemaPErr2(ctxt, node, child,
2625 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
2626 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002627 }
2628 ctxt->container = name;
2629
2630 child = node->children;
2631 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002632 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2633 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002634 }
2635 subtype = NULL;
2636
2637 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002638 subtype = (xmlSchemaTypePtr)
2639 xmlSchemaParseAll(ctxt, schema, child);
2640 child = child->next;
2641 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002642 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002643 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2644 child = child->next;
2645 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002646 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002647 subtype = (xmlSchemaTypePtr)
2648 xmlSchemaParseSequence(ctxt, schema, child);
2649 child = child->next;
2650 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002651 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002652 subtype = (xmlSchemaTypePtr)
2653 xmlSchemaParseGroup(ctxt, schema, child);
2654 child = child->next;
2655 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002656 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002657 if (IS_SCHEMA(child, "simpleType")) {
2658 subtype = (xmlSchemaTypePtr)
2659 xmlSchemaParseSimpleType(ctxt, schema, child);
2660 child = child->next;
2661 type->baseType = subtype;
2662 }
2663 /*
2664 * Facets
2665 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002666 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002667 (IS_SCHEMA(child, "minExclusive")) ||
2668 (IS_SCHEMA(child, "maxInclusive")) ||
2669 (IS_SCHEMA(child, "maxExclusive")) ||
2670 (IS_SCHEMA(child, "totalDigits")) ||
2671 (IS_SCHEMA(child, "fractionDigits")) ||
2672 (IS_SCHEMA(child, "pattern")) ||
2673 (IS_SCHEMA(child, "enumeration")) ||
2674 (IS_SCHEMA(child, "whiteSpace")) ||
2675 (IS_SCHEMA(child, "length")) ||
2676 (IS_SCHEMA(child, "maxLength")) ||
2677 (IS_SCHEMA(child, "minLength"))) {
2678 facet = xmlSchemaParseFacet(ctxt, schema, child);
2679 if (facet != NULL) {
2680 if (lastfacet == NULL) {
2681 type->facets = facet;
2682 lastfacet = facet;
2683 } else {
2684 lastfacet->next = facet;
2685 lastfacet = facet;
2686 }
2687 lastfacet->next = NULL;
2688 }
2689 child = child->next;
2690 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002691 }
2692 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2693 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002694 xmlSchemaPErr2(ctxt, node, child,
2695 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
2696 "Restriction %s has unexpected content\n",
2697 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002698 }
2699 ctxt->container = oldcontainer;
2700 return (type);
2701}
2702
2703/**
2704 * xmlSchemaParseExtension:
2705 * @ctxt: a schema validation context
2706 * @schema: the schema being built
2707 * @node: a subtree containing XML Schema informations
2708 *
2709 * parse a XML schema Extension definition
2710 * *WARNING* this interface is highly subject to change
2711 *
2712 * Returns the type definition or NULL in case of error
2713 */
2714static xmlSchemaTypePtr
2715xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002716 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002717{
2718 xmlSchemaTypePtr type, subtype;
2719 xmlNodePtr child = NULL;
2720 xmlChar name[30];
2721 xmlChar *oldcontainer;
2722
2723 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2724 return (NULL);
2725
2726 oldcontainer = ctxt->container;
2727
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002728 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002729 type = xmlSchemaAddType(ctxt, schema, name);
2730 if (type == NULL)
2731 return (NULL);
2732 type->node = node;
2733 type->type = XML_SCHEMA_TYPE_EXTENSION;
2734 type->id = xmlGetProp(node, BAD_CAST "id");
2735 ctxt->container = name;
2736
2737 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2738 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002739 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
2740 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002741 }
2742 child = node->children;
2743 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002744 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2745 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002746 }
2747 subtype = NULL;
2748
2749 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002750 subtype = xmlSchemaParseAll(ctxt, schema, child);
2751 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002752 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002753 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2754 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002755 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002756 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2757 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002758 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002759 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2760 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002761 }
2762 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002763 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002764 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2765 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002766 xmlSchemaPErr2(ctxt, node, child,
2767 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
2768 "Extension %s has unexpected content\n", type->name,
2769 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002770 }
2771 ctxt->container = oldcontainer;
2772 return (type);
2773}
2774
2775/**
2776 * xmlSchemaParseSimpleContent:
2777 * @ctxt: a schema validation context
2778 * @schema: the schema being built
2779 * @node: a subtree containing XML Schema informations
2780 *
2781 * parse a XML schema SimpleContent definition
2782 * *WARNING* this interface is highly subject to change
2783 *
2784 * Returns the type definition or NULL in case of error
2785 */
2786static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002787xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
2788 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002789{
2790 xmlSchemaTypePtr type, subtype;
2791 xmlNodePtr child = NULL;
2792 xmlChar name[30];
2793
2794 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2795 return (NULL);
2796
2797
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002798 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002799 type = xmlSchemaAddType(ctxt, schema, name);
2800 if (type == NULL)
2801 return (NULL);
2802 type->node = node;
2803 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
2804 type->id = xmlGetProp(node, BAD_CAST "id");
2805
2806 child = node->children;
2807 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002808 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2809 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002810 }
2811 subtype = NULL;
2812 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002813 subtype = (xmlSchemaTypePtr)
2814 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2815 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002816 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002817 subtype = (xmlSchemaTypePtr)
2818 xmlSchemaParseExtension(ctxt, schema, child);
2819 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002820 }
2821 type->subtypes = subtype;
2822 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002823 xmlSchemaPErr2(ctxt, node, child,
2824 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
2825 "SimpleContent %s has unexpected content\n",
2826 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002827 }
2828 return (type);
2829}
2830
2831/**
2832 * xmlSchemaParseComplexContent:
2833 * @ctxt: a schema validation context
2834 * @schema: the schema being built
2835 * @node: a subtree containing XML Schema informations
2836 *
2837 * parse a XML schema ComplexContent definition
2838 * *WARNING* this interface is highly subject to change
2839 *
2840 * Returns the type definition or NULL in case of error
2841 */
2842static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002843xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
2844 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002845{
2846 xmlSchemaTypePtr type, subtype;
2847 xmlNodePtr child = NULL;
2848 xmlChar name[30];
2849
2850 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2851 return (NULL);
2852
2853
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002854 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002855 type = xmlSchemaAddType(ctxt, schema, name);
2856 if (type == NULL)
2857 return (NULL);
2858 type->node = node;
2859 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
2860 type->id = xmlGetProp(node, BAD_CAST "id");
2861
2862 child = node->children;
2863 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002864 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2865 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002866 }
2867 subtype = NULL;
2868 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002869 subtype = (xmlSchemaTypePtr)
2870 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2871 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002872 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002873 subtype = (xmlSchemaTypePtr)
2874 xmlSchemaParseExtension(ctxt, schema, child);
2875 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002876 }
2877 type->subtypes = subtype;
2878 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002879 xmlSchemaPErr2(ctxt, node, child,
2880 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
2881 "ComplexContent %s has unexpected content\n",
2882 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002883 }
2884 return (type);
2885}
2886
2887/**
2888 * xmlSchemaParseComplexType:
2889 * @ctxt: a schema validation context
2890 * @schema: the schema being built
2891 * @node: a subtree containing XML Schema informations
2892 *
2893 * parse a XML schema Complex Type definition
2894 * *WARNING* this interface is highly subject to change
2895 *
2896 * Returns the type definition or NULL in case of error
2897 */
2898static xmlSchemaTypePtr
2899xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2900 xmlNodePtr node)
2901{
2902 xmlSchemaTypePtr type, subtype;
2903 xmlNodePtr child = NULL;
2904 xmlChar *name;
2905 xmlChar *oldcontainer;
2906
2907 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2908 return (NULL);
2909
2910 oldcontainer = ctxt->container;
2911 name = xmlGetProp(node, (const xmlChar *) "name");
2912 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002913 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002914
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002915 snprintf(buf, 99, "anontype%d", ctxt->counter++ + 1);
2916 name = xmlStrdup((xmlChar *) buf);
Daniel Veillard4255d502002-04-16 15:50:10 +00002917 }
2918 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002919 xmlSchemaPErr2(ctxt, node, child,
2920 XML_SCHEMAP_COMPLEXTYPE_NONAME_NOREF,
2921 "complexType has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002922 return (NULL);
2923 }
2924 type = xmlSchemaAddType(ctxt, schema, name);
2925 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002926 xmlFree(name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002927 return (NULL);
2928 }
2929 type->node = node;
2930 type->type = XML_SCHEMA_TYPE_COMPLEX;
2931 type->id = xmlGetProp(node, BAD_CAST "id");
2932 ctxt->container = name;
2933
2934 child = node->children;
2935 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002936 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2937 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002938 }
2939 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002940 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
2941 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002942 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002943 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
2944 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002945 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002946 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002947
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002948 if (IS_SCHEMA(child, "all")) {
2949 subtype = xmlSchemaParseAll(ctxt, schema, child);
2950 child = child->next;
2951 } else if (IS_SCHEMA(child, "choice")) {
2952 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2953 child = child->next;
2954 } else if (IS_SCHEMA(child, "sequence")) {
2955 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2956 child = child->next;
2957 } else if (IS_SCHEMA(child, "group")) {
2958 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2959 child = child->next;
2960 }
2961 if (subtype != NULL)
2962 type->subtypes = subtype;
2963 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002964 }
2965 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002966 xmlSchemaPErr2(ctxt, node, child,
2967 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
2968 "ComplexType %s has unexpected content\n",
2969 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002970 }
2971 ctxt->container = oldcontainer;
2972 xmlFree(name);
2973 return (type);
2974}
2975
2976
2977/**
2978 * xmlSchemaParseSchema:
2979 * @ctxt: a schema validation context
2980 * @node: a subtree containing XML Schema informations
2981 *
2982 * parse a XML schema definition from a node set
2983 * *WARNING* this interface is highly subject to change
2984 *
2985 * Returns the internal XML Schema structure built from the resource or
2986 * NULL in case of error
2987 */
2988static xmlSchemaPtr
2989xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2990{
2991 xmlSchemaPtr schema = NULL;
2992 xmlSchemaAnnotPtr annot;
2993 xmlNodePtr child = NULL;
2994 xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002995 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00002996
2997 if ((ctxt == NULL) || (node == NULL))
2998 return (NULL);
2999
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003000 nberrors = ctxt->nberrors;
3001 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003002 if (IS_SCHEMA(node, "schema")) {
3003 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003004 if (schema == NULL)
3005 return (NULL);
3006 schema->targetNamespace =
3007 xmlGetProp(node, BAD_CAST "targetNamespace");
3008 schema->id = xmlGetProp(node, BAD_CAST "id");
3009 schema->version = xmlGetProp(node, BAD_CAST "version");
3010 val = xmlGetProp(node, BAD_CAST "elementFormDefault");
3011 if (val != NULL) {
3012 if (xmlStrEqual(val, BAD_CAST "qualified"))
3013 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3014 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3015 xmlSchemaPErr2(ctxt, node, child,
3016 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3017 "Invalid value %s for elementFormDefault\n",
3018 val, NULL);
3019 }
3020 xmlFree(val);
3021 }
3022 val = xmlGetProp(node, BAD_CAST "attributeFormDefault");
3023 if (val != NULL) {
3024 if (xmlStrEqual(val, BAD_CAST "qualified"))
3025 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3026 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3027 xmlSchemaPErr2(ctxt, node, child,
3028 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3029 "Invalid value %s for attributeFormDefault\n",
3030 val, NULL);
3031 }
3032 xmlFree(val);
3033 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003034
3035 child = node->children;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003036 while ((IS_SCHEMA(child, "include")) ||
3037 (IS_SCHEMA(child, "import")) ||
3038 (IS_SCHEMA(child, "redefine")) ||
3039 (IS_SCHEMA(child, "annotation"))) {
3040 if (IS_SCHEMA(child, "annotation")) {
3041 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3042 if (schema->annot == NULL)
3043 schema->annot = annot;
3044 else
3045 xmlSchemaFreeAnnot(annot);
3046 } else if (IS_SCHEMA(child, "include")) {
3047 TODO} else if (IS_SCHEMA(child, "import")) {
3048 xmlSchemaParseImport(ctxt, schema, child);
3049 } else if (IS_SCHEMA(child, "redefine")) {
3050 TODO}
3051 child = child->next;
3052 }
3053 while (child != NULL) {
3054 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003055 xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003056 child = child->next;
3057 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003058 xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003059 child = child->next;
3060 } else if (IS_SCHEMA(child, "element")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003061 xmlSchemaParseElement(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003062 child = child->next;
3063 } else if (IS_SCHEMA(child, "attribute")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003064 xmlSchemaParseAttribute(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003065 child = child->next;
3066 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003067 xmlSchemaParseAttributeGroup(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003068 child = child->next;
3069 } else if (IS_SCHEMA(child, "group")) {
3070 xmlSchemaParseGroup(ctxt, schema, child);
3071 child = child->next;
3072 } else if (IS_SCHEMA(child, "notation")) {
3073 xmlSchemaParseNotation(ctxt, schema, child);
3074 child = child->next;
3075 } else {
3076 xmlSchemaPErr2(ctxt, node, child,
3077 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3078 "Schemas: unexpected element %s here \n",
3079 child->name, NULL);
3080 child = child->next;
3081 }
3082 while (IS_SCHEMA(child, "annotation")) {
3083 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3084 if (schema->annot == NULL)
3085 schema->annot = annot;
3086 else
3087 xmlSchemaFreeAnnot(annot);
3088 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003089 }
3090 }
3091 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003092 if (ctxt->nberrors != 0) {
3093 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003094 xmlSchemaFree(schema);
3095 schema = NULL;
3096 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003097 }
3098 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003099#ifdef DEBUG
3100 if (schema == NULL)
3101 xmlGenericError(xmlGenericErrorContext,
3102 "xmlSchemaParse() failed\n");
3103#endif
3104
3105 return (schema);
3106}
3107
3108/************************************************************************
3109 * *
3110 * Validating using Schemas *
3111 * *
3112 ************************************************************************/
3113
3114/************************************************************************
3115 * *
3116 * Reading/Writing Schemas *
3117 * *
3118 ************************************************************************/
3119
3120/**
3121 * xmlSchemaNewParserCtxt:
3122 * @URL: the location of the schema
3123 *
3124 * Create an XML Schemas parse context for that file/resource expected
3125 * to contain an XML Schemas file.
3126 *
3127 * Returns the parser context or NULL in case of error
3128 */
3129xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003130xmlSchemaNewParserCtxt(const char *URL)
3131{
Daniel Veillard4255d502002-04-16 15:50:10 +00003132 xmlSchemaParserCtxtPtr ret;
3133
3134 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003135 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003136
3137 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3138 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003139 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3140 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003141 return (NULL);
3142 }
3143 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003144 ret->URL = xmlStrdup((const xmlChar *) URL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003145 return (ret);
3146}
3147
3148/**
Daniel Veillard6045c902002-10-09 21:13:59 +00003149 * xmlSchemaNewMemParserCtxt:
3150 * @buffer: a pointer to a char array containing the schemas
3151 * @size: the size of the array
3152 *
3153 * Create an XML Schemas parse context for that memory buffer expected
3154 * to contain an XML Schemas file.
3155 *
3156 * Returns the parser context or NULL in case of error
3157 */
3158xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003159xmlSchemaNewMemParserCtxt(const char *buffer, int size)
3160{
Daniel Veillard6045c902002-10-09 21:13:59 +00003161 xmlSchemaParserCtxtPtr ret;
3162
3163 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003164 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003165
3166 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3167 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003168 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3169 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003170 return (NULL);
3171 }
3172 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3173 ret->buffer = buffer;
3174 ret->size = size;
3175 return (ret);
3176}
3177
3178/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003179 * xmlSchemaFreeParserCtxt:
3180 * @ctxt: the schema parser context
3181 *
3182 * Free the resources associated to the schema parser context
3183 */
3184void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003185xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
3186{
Daniel Veillard4255d502002-04-16 15:50:10 +00003187 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003188 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003189 if (ctxt->URL != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003190 xmlFree(ctxt->URL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003191 if (ctxt->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003192 xmlFreeDoc(ctxt->doc);
Daniel Veillard4255d502002-04-16 15:50:10 +00003193 xmlFree(ctxt);
3194}
3195
3196/************************************************************************
3197 * *
3198 * Building the content models *
3199 * *
3200 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003201
Daniel Veillard4255d502002-04-16 15:50:10 +00003202/**
3203 * xmlSchemaBuildAContentModel:
3204 * @type: the schema type definition
3205 * @ctxt: the schema parser context
3206 * @name: the element name whose content is being built
3207 *
3208 * Generate the automata sequence needed for that type
3209 */
3210static void
3211xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003212 xmlSchemaParserCtxtPtr ctxt,
3213 const xmlChar * name)
3214{
Daniel Veillard4255d502002-04-16 15:50:10 +00003215 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003216 xmlGenericError(xmlGenericErrorContext,
3217 "Found unexpected type = NULL in %s content model\n",
3218 name);
3219 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003220 }
3221 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003222 case XML_SCHEMA_TYPE_ANY:
3223 /* TODO : handle the namespace too */
3224 /* TODO : make that a specific transition type */
3225 TODO ctxt->state =
3226 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
3227 BAD_CAST "*", NULL);
3228 break;
3229 case XML_SCHEMA_TYPE_ELEMENT:{
3230 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00003231
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003232 /* TODO : handle the namespace too */
3233 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003234
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003235 if (elem->maxOccurs >= UNBOUNDED) {
3236 if (elem->minOccurs > 1) {
3237 xmlAutomataStatePtr tmp;
3238 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003239
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003240 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3241 oldstate,
3242 NULL);
3243 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003244
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003245 counter = xmlAutomataNewCounter(ctxt->am,
3246 elem->minOccurs -
3247 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00003248
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003249 if (elem->refDecl != NULL) {
3250 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3251 elem->refDecl,
3252 ctxt,
3253 elem->refDecl->
3254 name);
3255 } else {
3256 ctxt->state =
3257 xmlAutomataNewTransition(ctxt->am,
3258 ctxt->state, NULL,
3259 elem->name, type);
3260 }
3261 tmp = ctxt->state;
3262 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3263 counter);
3264 ctxt->state =
3265 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3266 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00003267
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003268 } else {
3269 if (elem->refDecl != NULL) {
3270 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3271 elem->refDecl,
3272 ctxt,
3273 elem->refDecl->
3274 name);
3275 } else {
3276 ctxt->state =
3277 xmlAutomataNewTransition(ctxt->am,
3278 ctxt->state, NULL,
3279 elem->name, type);
3280 }
3281 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3282 oldstate);
3283 if (elem->minOccurs == 0) {
3284 /* basically an elem* */
3285 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3286 ctxt->state);
3287 }
3288 }
3289 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3290 xmlAutomataStatePtr tmp;
3291 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003292
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003293 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3294 oldstate, NULL);
3295 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003296
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003297 counter = xmlAutomataNewCounter(ctxt->am,
3298 elem->minOccurs - 1,
3299 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003300
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003301 if (elem->refDecl != NULL) {
3302 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3303 elem->refDecl, ctxt,
3304 elem->refDecl->name);
3305 } else {
3306 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3307 ctxt->state,
3308 NULL,
3309 elem->name,
3310 type);
3311 }
3312 tmp = ctxt->state;
3313 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3314 counter);
3315 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3316 NULL,
3317 counter);
3318 if (elem->minOccurs == 0) {
3319 /* basically an elem? */
3320 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3321 ctxt->state);
3322 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00003323
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003324 } else {
3325 if (elem->refDecl != NULL) {
3326 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3327 elem->refDecl, ctxt,
3328 elem->refDecl->name);
3329 } else {
3330 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3331 ctxt->state,
3332 NULL,
3333 elem->name,
3334 type);
3335 }
3336 if (elem->minOccurs == 0) {
3337 /* basically an elem? */
3338 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3339 ctxt->state);
3340 }
3341 }
3342 break;
3343 }
3344 case XML_SCHEMA_TYPE_SEQUENCE:{
3345 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003346
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003347 /*
3348 * If max and min occurances are default (1) then
3349 * simply iterate over the subtypes
3350 */
3351 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
3352 subtypes = type->subtypes;
3353 while (subtypes != NULL) {
3354 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3355 subtypes = subtypes->next;
3356 }
3357 } else {
3358 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003359
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003360 if (type->maxOccurs >= UNBOUNDED) {
3361 if (type->minOccurs > 1) {
3362 xmlAutomataStatePtr tmp;
3363 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003364
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003365 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3366 oldstate,
3367 NULL);
3368 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003369
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003370 counter = xmlAutomataNewCounter(ctxt->am,
3371 type->
3372 minOccurs - 1,
3373 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00003374
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003375 subtypes = type->subtypes;
3376 while (subtypes != NULL) {
3377 xmlSchemaBuildAContentModel(subtypes, ctxt,
3378 name);
3379 subtypes = subtypes->next;
3380 }
3381 tmp = ctxt->state;
3382 xmlAutomataNewCountedTrans(ctxt->am, tmp,
3383 oldstate, counter);
3384 ctxt->state =
3385 xmlAutomataNewCounterTrans(ctxt->am, tmp,
3386 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00003387
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003388 } else {
3389 subtypes = type->subtypes;
3390 while (subtypes != NULL) {
3391 xmlSchemaBuildAContentModel(subtypes, ctxt,
3392 name);
3393 subtypes = subtypes->next;
3394 }
3395 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3396 oldstate);
3397 if (type->minOccurs == 0) {
3398 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3399 ctxt->state);
3400 }
3401 }
3402 } else if ((type->maxOccurs > 1)
3403 || (type->minOccurs > 1)) {
3404 xmlAutomataStatePtr tmp;
3405 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00003406
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003407 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3408 oldstate,
3409 NULL);
3410 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00003411
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003412 counter = xmlAutomataNewCounter(ctxt->am,
3413 type->minOccurs -
3414 1,
3415 type->maxOccurs -
3416 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003417
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003418 subtypes = type->subtypes;
3419 while (subtypes != NULL) {
3420 xmlSchemaBuildAContentModel(subtypes, ctxt,
3421 name);
3422 subtypes = subtypes->next;
3423 }
3424 tmp = ctxt->state;
3425 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3426 counter);
3427 ctxt->state =
3428 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3429 counter);
3430 if (type->minOccurs == 0) {
3431 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3432 ctxt->state);
3433 }
Daniel Veillardb509f152002-04-17 16:28:10 +00003434
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003435 } else {
3436 subtypes = type->subtypes;
3437 while (subtypes != NULL) {
3438 xmlSchemaBuildAContentModel(subtypes, ctxt,
3439 name);
3440 subtypes = subtypes->next;
3441 }
3442 if (type->minOccurs == 0) {
3443 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3444 ctxt->state);
3445 }
3446 }
3447 }
3448 break;
3449 }
3450 case XML_SCHEMA_TYPE_CHOICE:{
3451 xmlSchemaTypePtr subtypes;
3452 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00003453
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003454 start = ctxt->state;
3455 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00003456
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003457 /*
3458 * iterate over the subtypes and remerge the end with an
3459 * epsilon transition
3460 */
3461 if (type->maxOccurs == 1) {
3462 subtypes = type->subtypes;
3463 while (subtypes != NULL) {
3464 ctxt->state = start;
3465 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3466 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
3467 subtypes = subtypes->next;
3468 }
3469 } else {
3470 int counter;
3471 xmlAutomataStatePtr hop;
3472 int maxOccurs = type->maxOccurs == UNBOUNDED ?
3473 UNBOUNDED : type->maxOccurs - 1;
3474 int minOccurs =
3475 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00003476
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003477 /*
3478 * use a counter to keep track of the number of transtions
3479 * which went through the choice.
3480 */
3481 counter =
3482 xmlAutomataNewCounter(ctxt->am, minOccurs,
3483 maxOccurs);
3484 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00003485
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003486 subtypes = type->subtypes;
3487 while (subtypes != NULL) {
3488 ctxt->state = start;
3489 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3490 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
3491 subtypes = subtypes->next;
3492 }
3493 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
3494 counter);
3495 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
3496 counter);
3497 }
3498 if (type->minOccurs == 0) {
3499 xmlAutomataNewEpsilon(ctxt->am, start, end);
3500 }
3501 ctxt->state = end;
3502 break;
3503 }
3504 case XML_SCHEMA_TYPE_ALL:{
3505 xmlAutomataStatePtr start;
3506 xmlSchemaTypePtr subtypes;
3507 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3508 int lax;
3509
3510 subtypes = type->subtypes;
3511 if (subtypes == NULL)
3512 break;
3513 start = ctxt->state;
3514 while (subtypes != NULL) {
3515 ctxt->state = start;
3516 elem = (xmlSchemaElementPtr) subtypes;
3517
3518 /* TODO : handle the namespace too */
3519 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
3520 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
3521 ctxt->state, elem->name, 1,
3522 1, subtypes);
3523 } else {
3524 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
3525 ctxt->state, elem->name,
3526 elem->minOccurs,
3527 elem->maxOccurs,
3528 subtypes);
3529 }
3530 subtypes = subtypes->next;
3531 }
3532 lax = type->minOccurs == 0;
3533 ctxt->state =
3534 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
3535 lax);
3536 break;
3537 }
3538 case XML_SCHEMA_TYPE_RESTRICTION:
3539 if (type->subtypes != NULL)
3540 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3541 break;
3542 case XML_SCHEMA_TYPE_EXTENSION:
3543 if (type->baseType != NULL) {
3544 xmlSchemaTypePtr subtypes;
3545
3546 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
3547 subtypes = type->subtypes;
3548 while (subtypes != NULL) {
3549 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3550 subtypes = subtypes->next;
3551 }
3552 } else if (type->subtypes != NULL)
3553 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3554 break;
3555 case XML_SCHEMA_TYPE_GROUP:
3556 if (type->subtypes == NULL) {
3557 }
3558 case XML_SCHEMA_TYPE_COMPLEX:
3559 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
3560 if (type->subtypes != NULL)
3561 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3562 break;
3563 default:
3564 xmlGenericError(xmlGenericErrorContext,
3565 "Found unexpected type %d in %s content model\n",
3566 type->type, name);
3567 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003568 }
3569}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003570
Daniel Veillard4255d502002-04-16 15:50:10 +00003571/**
3572 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003573 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00003574 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003575 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00003576 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003577 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00003578 */
3579static void
3580xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003581 xmlSchemaParserCtxtPtr ctxt,
3582 const xmlChar * name)
3583{
Daniel Veillard4255d502002-04-16 15:50:10 +00003584 xmlAutomataStatePtr start;
3585
Daniel Veillard4255d502002-04-16 15:50:10 +00003586 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003587 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003588 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003589 elem->contentType = XML_SCHEMA_CONTENT_ANY;
3590 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003591 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003592 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003593 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003594 if (elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003595 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003596
3597#ifdef DEBUG_CONTENT
3598 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003599 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003600#endif
3601
Daniel Veillard4255d502002-04-16 15:50:10 +00003602 ctxt->am = xmlNewAutomata();
3603 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003604 xmlGenericError(xmlGenericErrorContext,
3605 "Cannot create automata for elem %s\n", name);
3606 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003607 }
3608 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3609 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3610 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00003611 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003612 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003613 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
3614 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003615 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003616 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
3617 "Content model of %s is not determinist:\n", name,
3618 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00003619 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00003620#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003621 xmlGenericError(xmlGenericErrorContext,
3622 "Content model of %s:\n", name);
3623 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003624#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00003625 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003626 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003627 xmlFreeAutomata(ctxt->am);
3628 ctxt->am = NULL;
3629}
3630
3631/**
3632 * xmlSchemaRefFixupCallback:
3633 * @elem: the schema element context
3634 * @ctxt: the schema parser context
3635 *
3636 * Free the resources associated to the schema parser context
3637 */
3638static void
3639xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003640 xmlSchemaParserCtxtPtr ctxt,
3641 const xmlChar * name,
3642 const xmlChar * context ATTRIBUTE_UNUSED,
3643 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003644{
3645 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003646 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003647 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003648 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003649
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650 if (elem->subtypes != NULL) {
3651 xmlSchemaPErr(ctxt, elem->node,
3652 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
3653 "Schemas: element %s have both ref and subtype\n",
3654 name, NULL);
3655 return;
3656 }
3657 elemDecl = xmlHashLookup2(ctxt->schema->elemDecl,
3658 elem->ref, elem->refNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00003659
3660 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003661 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
3662 "Schemas: element %s ref to %s not found\n",
3663 name, elem->ref);
3664 return;
3665 }
3666 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003667 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003668 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003669
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003670 if (elem->subtypes != NULL) {
3671 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
3672 "Schemas: element %s have both type and subtype\n",
3673 name, NULL);
3674 return;
3675 }
3676 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3677 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00003678
3679 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003680 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
3681 "Schemas: element %s type %s not found\n", name,
3682 elem->namedType);
3683 return;
3684 }
3685 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00003686 }
3687}
3688
3689/**
3690 * xmlSchemaTypeFixup:
3691 * @typeDecl: the schema type definition
3692 * @ctxt: the schema parser context
3693 *
3694 * Fixes the content model of the type.
3695 */
3696static void
3697xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003698 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003699{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00003700 if (typeDecl == NULL)
3701 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003702 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003703 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00003704 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003705 switch (typeDecl->type) {
3706 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
3707 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3708 if (typeDecl->subtypes != NULL)
3709 typeDecl->contentType =
3710 typeDecl->subtypes->contentType;
3711 break;
3712 }
3713 case XML_SCHEMA_TYPE_RESTRICTION:{
3714 if (typeDecl->subtypes != NULL)
3715 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003716
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003717 if (typeDecl->base != NULL) {
3718 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00003719
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003720 baseType =
3721 xmlSchemaGetType(ctxt->schema, typeDecl->base,
3722 typeDecl->baseNs);
3723 if (baseType == NULL) {
3724 xmlSchemaPErr(ctxt, typeDecl->node,
3725 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00003726 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003727 name, typeDecl->base);
3728 }
3729 typeDecl->baseType = baseType;
3730 }
3731 if (typeDecl->subtypes == NULL)
3732 /* 1.1.1 */
3733 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3734 else if ((typeDecl->subtypes->subtypes == NULL) &&
3735 ((typeDecl->subtypes->type ==
3736 XML_SCHEMA_TYPE_ALL)
3737 || (typeDecl->subtypes->type ==
3738 XML_SCHEMA_TYPE_SEQUENCE)))
3739 /* 1.1.2 */
3740 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3741 else if ((typeDecl->subtypes->type ==
3742 XML_SCHEMA_TYPE_CHOICE)
3743 && (typeDecl->subtypes->subtypes == NULL))
3744 /* 1.1.3 */
3745 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3746 else {
3747 /* 1.2 and 2.X are applied at the other layer */
3748 typeDecl->contentType =
3749 XML_SCHEMA_CONTENT_ELEMENTS;
3750 }
3751 break;
3752 }
3753 case XML_SCHEMA_TYPE_EXTENSION:{
3754 xmlSchemaContentType explicitContentType;
3755 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00003756
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003757 if (typeDecl->base != NULL) {
3758 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00003759
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003760 baseType =
3761 xmlSchemaGetType(ctxt->schema, typeDecl->base,
3762 typeDecl->baseNs);
3763 if (baseType == NULL) {
3764 xmlSchemaPErr(ctxt, typeDecl->node,
3765 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00003766 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003767 name, typeDecl->base);
3768 }
3769 typeDecl->baseType = baseType;
3770 }
3771 if (typeDecl->subtypes != NULL)
3772 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003773
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003774 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
3775 if (typeDecl->subtypes == NULL)
3776 /* 1.1.1 */
3777 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3778 else if ((typeDecl->subtypes->subtypes == NULL) &&
3779 ((typeDecl->subtypes->type ==
3780 XML_SCHEMA_TYPE_ALL)
3781 || (typeDecl->subtypes->type ==
3782 XML_SCHEMA_TYPE_SEQUENCE)))
3783 /* 1.1.2 */
3784 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3785 else if ((typeDecl->subtypes->type ==
3786 XML_SCHEMA_TYPE_CHOICE)
3787 && (typeDecl->subtypes->subtypes == NULL))
3788 /* 1.1.3 */
3789 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00003790
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003791 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3792 typeDecl->baseNs);
3793 if (base == NULL) {
3794 xmlSchemaPErr(ctxt, typeDecl->node,
3795 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
3796 "Schemas: base type %s of type %s not found\n",
3797 typeDecl->base, name);
3798 return;
3799 }
3800 xmlSchemaTypeFixup(base, ctxt, NULL);
3801 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
3802 /* 2.1 */
3803 typeDecl->contentType = base->contentType;
3804 } else if (base->contentType ==
3805 XML_SCHEMA_CONTENT_EMPTY) {
3806 /* 2.2 imbitable ! */
3807 typeDecl->contentType =
3808 XML_SCHEMA_CONTENT_ELEMENTS;
3809 } else {
3810 /* 2.3 imbitable pareil ! */
3811 typeDecl->contentType =
3812 XML_SCHEMA_CONTENT_ELEMENTS;
3813 }
3814 break;
3815 }
3816 case XML_SCHEMA_TYPE_COMPLEX:{
3817 if (typeDecl->subtypes == NULL) {
3818 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3819 } else {
3820 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3821 typeDecl->contentType =
3822 XML_SCHEMA_CONTENT_MIXED;
3823 else {
3824 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
3825 NULL);
3826 if (typeDecl->subtypes != NULL)
3827 typeDecl->contentType =
3828 typeDecl->subtypes->contentType;
3829 }
3830 }
3831 break;
3832 }
3833 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
3834 if (typeDecl->subtypes == NULL) {
3835 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3836 } else {
3837 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3838 typeDecl->contentType =
3839 XML_SCHEMA_CONTENT_MIXED;
3840 else {
3841 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
3842 NULL);
3843 if (typeDecl->subtypes != NULL)
3844 typeDecl->contentType =
3845 typeDecl->subtypes->contentType;
3846 }
3847 }
3848 break;
3849 }
3850 case XML_SCHEMA_TYPE_SEQUENCE:
3851 case XML_SCHEMA_TYPE_GROUP:
3852 case XML_SCHEMA_TYPE_ALL:
3853 case XML_SCHEMA_TYPE_CHOICE:
3854 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3855 break;
3856 case XML_SCHEMA_TYPE_BASIC:
3857 case XML_SCHEMA_TYPE_ANY:
3858 case XML_SCHEMA_TYPE_FACET:
3859 case XML_SCHEMA_TYPE_SIMPLE:
3860 case XML_SCHEMA_TYPE_UR:
3861 case XML_SCHEMA_TYPE_ELEMENT:
3862 case XML_SCHEMA_TYPE_ATTRIBUTE:
3863 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
3864 case XML_SCHEMA_TYPE_NOTATION:
3865 case XML_SCHEMA_TYPE_LIST:
3866 case XML_SCHEMA_TYPE_UNION:
3867 case XML_SCHEMA_FACET_MININCLUSIVE:
3868 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3869 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3870 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
3871 case XML_SCHEMA_FACET_TOTALDIGITS:
3872 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3873 case XML_SCHEMA_FACET_PATTERN:
3874 case XML_SCHEMA_FACET_ENUMERATION:
3875 case XML_SCHEMA_FACET_WHITESPACE:
3876 case XML_SCHEMA_FACET_LENGTH:
3877 case XML_SCHEMA_FACET_MAXLENGTH:
3878 case XML_SCHEMA_FACET_MINLENGTH:
3879 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
3880 break;
3881 }
3882 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003883#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003884 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003885 xmlGenericError(xmlGenericErrorContext,
3886 "Type of %s : %s:%d :", name,
3887 typeDecl->node->doc->URL,
3888 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003889 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003890 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003891 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003892 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003893 case XML_SCHEMA_CONTENT_SIMPLE:
3894 xmlGenericError(xmlGenericErrorContext, "simple\n");
3895 break;
3896 case XML_SCHEMA_CONTENT_ELEMENTS:
3897 xmlGenericError(xmlGenericErrorContext, "elements\n");
3898 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003899 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003900 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
3901 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003902 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003903 xmlGenericError(xmlGenericErrorContext, "empty\n");
3904 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003905 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003906 xmlGenericError(xmlGenericErrorContext, "mixed\n");
3907 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003908 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003909 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
3910 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003911 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003912 xmlGenericError(xmlGenericErrorContext, "basic\n");
3913 break;
3914 default:
3915 xmlGenericError(xmlGenericErrorContext,
3916 "not registered !!!\n");
3917 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00003918 }
3919#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003920}
3921
3922/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003923 * xmlSchemaCheckFacet:
3924 * @facet: the facet
3925 * @typeDecl: the schema type definition
3926 * @ctxt: the schema parser context or NULL
3927 * @name: name of the type
3928 *
3929 * Checks the default values types, especially for facets
3930 *
3931 * Returns 0 if okay or -1 in cae of error
3932 */
3933int
3934xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003935 xmlSchemaTypePtr typeDecl,
3936 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003937{
3938 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
3939 int ret = 0;
3940
3941 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003942 nonNegativeIntegerType =
3943 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
3944 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003945 }
3946 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003947 case XML_SCHEMA_FACET_MININCLUSIVE:
3948 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3949 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3950 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
3951 /*
3952 * Okay we need to validate the value
3953 * at that point.
3954 */
3955 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003956
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003957 vctxt = xmlSchemaNewValidCtxt(NULL);
3958 if (vctxt == NULL)
3959 break;
3960 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3961 facet->value);
3962 facet->val = vctxt->value;
3963 vctxt->value = NULL;
3964 if (facet->val == NULL) {
3965 /* error code */
3966 if (ctxt != NULL) {
3967 xmlSchemaPErr(ctxt, facet->node,
3968 XML_SCHEMAP_INVALID_FACET,
3969 "Schemas: type %s facet value %s invalid\n",
3970 name, facet->value);
3971 }
3972 ret = -1;
3973 }
3974 xmlSchemaFreeValidCtxt(vctxt);
3975 break;
3976 }
3977 case XML_SCHEMA_FACET_ENUMERATION:{
3978 /*
3979 * Okay we need to validate the value
3980 * at that point.
3981 */
3982 xmlSchemaValidCtxtPtr vctxt;
3983 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003984
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003985 vctxt = xmlSchemaNewValidCtxt(NULL);
3986 if (vctxt == NULL)
3987 break;
3988 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3989 facet->value);
3990 if (tmp != 0) {
3991 if (ctxt != NULL) {
3992 xmlSchemaPErr(ctxt, facet->node,
3993 XML_SCHEMAP_INVALID_ENUM,
3994 "Schemas: type %s enumeration value %s invalid\n",
3995 name, facet->value);
3996 }
3997 ret = -1;
3998 }
3999 xmlSchemaFreeValidCtxt(vctxt);
4000 break;
4001 }
4002 case XML_SCHEMA_FACET_PATTERN:
4003 facet->regexp = xmlRegexpCompile(facet->value);
4004 if (facet->regexp == NULL) {
4005 xmlSchemaPErr(ctxt, typeDecl->node,
4006 XML_SCHEMAP_REGEXP_INVALID,
4007 "Schemas: type %s facet regexp %s invalid\n",
4008 name, facet->value);
4009 ret = -1;
4010 }
4011 break;
4012 case XML_SCHEMA_FACET_TOTALDIGITS:
4013 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4014 case XML_SCHEMA_FACET_LENGTH:
4015 case XML_SCHEMA_FACET_MAXLENGTH:
4016 case XML_SCHEMA_FACET_MINLENGTH:{
4017 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004018
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004019 tmp =
4020 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4021 facet->value,
4022 &facet->val);
4023 if (tmp != 0) {
4024 /* error code */
4025 if (ctxt != NULL) {
4026 xmlSchemaPErr(ctxt, facet->node,
4027 XML_SCHEMAP_INVALID_FACET_VALUE,
4028 "Schemas: type %s facet value %s invalid\n",
4029 name, facet->value);
4030 }
4031 ret = -1;
4032 }
4033 break;
4034 }
4035 case XML_SCHEMA_FACET_WHITESPACE:{
4036 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4037 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4038 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4039 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4040 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4041 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4042 } else {
4043 if (ctxt != NULL) {
4044 xmlSchemaPErr(ctxt, facet->node,
4045 XML_SCHEMAP_INVALID_WHITE_SPACE,
4046 "Schemas: type %s whiteSpace value %s invalid\n",
4047 name, facet->value);
4048 }
4049 ret = -1;
4050 }
4051 }
4052 default:
4053 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004054 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004055 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004056}
4057
4058/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004059 * xmlSchemaCheckDefaults:
4060 * @typeDecl: the schema type definition
4061 * @ctxt: the schema parser context
4062 *
4063 * Checks the default values types, especially for facets
4064 */
4065static void
4066xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004067 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004068{
Daniel Veillard4255d502002-04-16 15:50:10 +00004069 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004070 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004071 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004072 if (typeDecl->facets != NULL) {
4073 xmlSchemaFacetPtr facet = typeDecl->facets;
4074
4075 while (facet != NULL) {
4076 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4077 facet = facet->next;
4078 }
4079 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004080 }
4081}
4082
4083/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004084 * xmlSchemaAttrGrpFixup:
4085 * @attrgrpDecl: the schema attribute definition
4086 * @ctxt: the schema parser context
4087 * @name: the attribute name
4088 *
4089 * Fixes finish doing the computations on the attributes definitions
4090 */
4091static void
4092xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004093 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004094{
4095 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004096 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004097 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004098 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004099 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004100 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004101
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004102 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4103 attrgrpDecl->refNs);
4104 if (ref == NULL) {
4105 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4106 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4107 "Schemas: attribute group %s reference %s not found\n",
4108 name, attrgrpDecl->ref);
4109 return;
4110 }
4111 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4112 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004113 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004114 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4115 "Schemas: attribute %s has no attributes nor reference\n",
4116 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004117 }
4118}
4119
4120/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004121 * xmlSchemaAttrFixup:
4122 * @attrDecl: 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
4129xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004130 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004131{
4132 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004133 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004134 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004135 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004136 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004137 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004138
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004139 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4140 attrDecl->typeNs);
4141 if (type == NULL) {
4142 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4143 "Schemas: attribute %s type %s not found\n",
4144 name, attrDecl->typeName);
4145 }
4146 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004147 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004148 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004149
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004150 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4151 attrDecl->refNs);
4152 if (ref == NULL) {
4153 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4154 "Schemas: attribute %s reference %s not found\n",
4155 name, attrDecl->ref);
4156 return;
4157 }
4158 xmlSchemaAttrFixup(ref, ctxt, NULL);
4159 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004160 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004161 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4162 "Schemas: attribute %s has no type nor reference\n",
4163 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004164 }
4165}
4166
4167/**
4168 * xmlSchemaParse:
4169 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004170 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004171 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004172 * XML Shema struture which can be used to validate instances.
4173 * *WARNING* this interface is highly subject to change
4174 *
4175 * Returns the internal XML Schema structure built from the resource or
4176 * NULL in case of error
4177 */
4178xmlSchemaPtr
4179xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4180{
4181 xmlSchemaPtr ret = NULL;
4182 xmlDocPtr doc;
4183 xmlNodePtr root, cur, delete;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004184 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004185
4186 xmlSchemaInitTypes();
4187
Daniel Veillard6045c902002-10-09 21:13:59 +00004188 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004189 return (NULL);
4190
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004191 nberrors = ctxt->nberrors;
4192 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004193 ctxt->counter = 0;
4194 ctxt->container = NULL;
4195
4196 /*
4197 * First step is to parse the input document into an DOM/Infoset
4198 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004199 if (ctxt->URL != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004200 doc = xmlParseFile((const char *) ctxt->URL);
4201 if (doc == NULL) {
4202 xmlSchemaPErr(ctxt, NULL,
4203 XML_SCHEMAP_FAILED_LOAD,
4204 "xmlSchemaParse: could not load %s\n",
4205 ctxt->URL, NULL);
4206 return (NULL);
4207 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004208 } else if (ctxt->buffer != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004209 doc = xmlParseMemory(ctxt->buffer, ctxt->size);
4210 if (doc == NULL) {
4211 xmlSchemaPErr(ctxt, NULL,
4212 XML_SCHEMAP_FAILED_PARSE,
4213 "xmlSchemaParse: could not parse\n",
4214 NULL, NULL);
4215 return (NULL);
4216 }
4217 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
4218 ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard6045c902002-10-09 21:13:59 +00004219 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004220 xmlSchemaPErr(ctxt, NULL,
4221 XML_SCHEMAP_NOTHING_TO_PARSE,
4222 "xmlSchemaParse: could not parse\n",
4223 NULL, NULL);
4224 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004225 }
4226
4227 /*
4228 * Then extract the root and Schema parse it
4229 */
4230 root = xmlDocGetRootElement(doc);
4231 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004232 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4233 XML_SCHEMAP_NOROOT,
4234 "schemas has no root", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004235 return (NULL);
4236 }
4237
4238 /*
4239 * Remove all the blank text nodes
4240 */
4241 delete = NULL;
4242 cur = root;
4243 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004244 if (delete != NULL) {
4245 xmlUnlinkNode(delete);
4246 xmlFreeNode(delete);
4247 delete = NULL;
4248 }
4249 if (cur->type == XML_TEXT_NODE) {
4250 if (IS_BLANK_NODE(cur)) {
4251 if (xmlNodeGetSpacePreserve(cur) != 1) {
4252 delete = cur;
4253 }
4254 }
4255 } else if ((cur->type != XML_ELEMENT_NODE) &&
4256 (cur->type != XML_CDATA_SECTION_NODE)) {
4257 delete = cur;
4258 goto skip_children;
4259 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004260
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004261 /*
4262 * Skip to next node
4263 */
4264 if (cur->children != NULL) {
4265 if ((cur->children->type != XML_ENTITY_DECL) &&
4266 (cur->children->type != XML_ENTITY_REF_NODE) &&
4267 (cur->children->type != XML_ENTITY_NODE)) {
4268 cur = cur->children;
4269 continue;
4270 }
4271 }
4272 skip_children:
4273 if (cur->next != NULL) {
4274 cur = cur->next;
4275 continue;
4276 }
4277
4278 do {
4279 cur = cur->parent;
4280 if (cur == NULL)
4281 break;
4282 if (cur == root) {
4283 cur = NULL;
4284 break;
4285 }
4286 if (cur->next != NULL) {
4287 cur = cur->next;
4288 break;
4289 }
4290 } while (cur != NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004291 }
4292 if (delete != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004293 xmlUnlinkNode(delete);
4294 xmlFreeNode(delete);
4295 delete = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004296 }
4297
4298 /*
4299 * Then do the parsing for good
4300 */
4301 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillardb4398962002-04-19 07:01:55 +00004302 if (ret == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004303 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004304 ret->doc = doc;
4305
4306 /*
4307 * Then fix all the references.
4308 */
4309 ctxt->schema = ret;
4310 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004311 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004312
4313 /*
4314 * Then fixup all types properties
4315 */
4316 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4317
4318 /*
4319 * Then build the content model for all elements
4320 */
4321 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004322 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004323
4324 /*
4325 * Then check the defaults part of the type like facets values
4326 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004327 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
4328 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004329
4330 /*
4331 * Then fixup all attributes declarations
4332 */
4333 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4334
Daniel Veillard13e04c62002-04-23 17:51:29 +00004335 /*
4336 * Then fixup all attributes group declarations
4337 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004338 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
4339 ctxt);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004340
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004341 if (ctxt->nberrors != 0) {
4342 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004343 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004344 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004345 return (ret);
4346}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004347
Daniel Veillard4255d502002-04-16 15:50:10 +00004348/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00004349 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00004350 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00004351 * @err: the error callback
4352 * @warn: the warning callback
4353 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00004354 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004355 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004356 */
4357void
4358xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004359 xmlSchemaValidityErrorFunc err,
4360 xmlSchemaValidityWarningFunc warn, void *ctx)
4361{
Daniel Veillard4255d502002-04-16 15:50:10 +00004362 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004363 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004364 ctxt->error = err;
4365 ctxt->warning = warn;
4366 ctxt->userData = ctx;
4367}
4368
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004369/**
4370 * xmlSchemaFacetTypeToString:
4371 * @type: the facet type
4372 *
4373 * Convert the xmlSchemaTypeType to a char string.
4374 *
4375 * Returns the char string representation of the facet type if the
4376 * type is a facet and an "Internal Error" string otherwise.
4377 */
4378static const char *
4379xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
4380{
4381 switch (type) {
4382 case XML_SCHEMA_FACET_PATTERN:
4383 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004384 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004385 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004386 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004387 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004388 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004389 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004390 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004391 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004392 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004393 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004394 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004395 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004396 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004397 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004398 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004399 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004400 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004401 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004402 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004403 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004404 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004405 return ("fractionDigits");
4406 default:
4407 break;
4408 }
4409 return ("Internal Error");
4410}
4411
4412/**
4413 * xmlSchemaValidateFacets:
4414 * @ctxt: a schema validation context
4415 * @base: the base type
4416 * @facets: the list of facets to check
4417 * @value: the lexical repr of the value to validate
4418 * @val: the precomputed value
4419 *
4420 * Check a value against all facet conditions
4421 *
4422 * Returns 0 if the element is schemas valid, a positive error code
4423 * number otherwise and -1 in case of internal or API error.
4424 */
4425static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004426xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
4427 xmlSchemaTypePtr base,
4428 xmlSchemaFacetPtr facets, xmlChar * value)
4429{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004430 int ret = 0;
4431 int tmp = 0;
4432 xmlSchemaTypeType type;
4433 xmlSchemaFacetPtr facet = facets;
4434
4435 while (facet != NULL) {
4436 type = facet->type;
4437 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004438 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004439
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004440 while (facet != NULL) {
4441 tmp =
4442 xmlSchemaValidateFacet(base, facet, value,
4443 ctxt->value);
4444 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004445 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004446 }
4447 facet = facet->next;
4448 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004449 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004450 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004451
4452 if (tmp != 0) {
4453 ret = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004454 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 +00004455 }
4456 if (facet != NULL)
4457 facet = facet->next;
4458 }
4459 return (ret);
4460}
4461
Daniel Veillard4255d502002-04-16 15:50:10 +00004462/************************************************************************
4463 * *
4464 * Simple type validation *
4465 * *
4466 ************************************************************************/
4467
4468/**
4469 * xmlSchemaValidateSimpleValue:
4470 * @ctxt: a schema validation context
4471 * @type: the type declaration
4472 * @value: the value to validate
4473 *
4474 * Validate a value against a simple type
4475 *
4476 * Returns 0 if the value is valid, a positive error code
4477 * number otherwise and -1 in case of internal or API error.
4478 */
4479static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004480xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
4481 xmlSchemaTypePtr type, xmlChar * value)
4482{
Daniel Veillard4255d502002-04-16 15:50:10 +00004483 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004484
Daniel Veillard4255d502002-04-16 15:50:10 +00004485 /*
4486 * First normalize the value accordingly to Schema Datatype
4487 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
4488 */
4489 /*
4490 * Then check the normalized value against the lexical space of the
4491 * type.
4492 */
4493 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004494 if (ctxt->value != NULL) {
4495 xmlSchemaFreeValue(ctxt->value);
4496 ctxt->value = NULL;
4497 }
4498 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
4499 ctxt->cur);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004500 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004501 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 +00004502 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004503 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004504 xmlSchemaTypePtr base;
4505 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00004506
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004507 base = type->baseType;
4508 if (base != NULL) {
4509 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4510 } else if (type->subtypes != NULL) {
4511
4512 }
4513 /*
4514 * Do not validate facets when working on building the Schemas
4515 */
4516 if (ctxt->schema != NULL) {
4517 if (ret == 0) {
4518 facet = type->facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004519 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004520 }
4521 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004522 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004523 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004524
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004525 base = type->subtypes;
4526 if (base != NULL) {
4527 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4528 } else {
4529 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00004530 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004531 xmlSchemaTypePtr base;
4532 xmlChar *cur, *end, tmp;
4533 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00004534
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004535 base = type->subtypes;
4536 if (base == NULL) {
4537 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
4538 "Internal: List type %s has no base type\n",
4539 type->name, NULL);
4540 return (-1);
4541 }
4542 cur = value;
4543 do {
4544 while (IS_BLANK(*cur))
4545 cur++;
4546 end = cur;
4547 while ((*end != 0) && (!(IS_BLANK(*end))))
4548 end++;
4549 if (end == cur)
4550 break;
4551 tmp = *end;
4552 *end = 0;
4553 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, cur);
4554 if (ret2 != 0)
4555 ret = 1;
4556 *end = tmp;
4557 cur = end;
4558 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004559 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004560 TODO}
4561 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004562}
4563
4564/************************************************************************
4565 * *
4566 * DOM Validation code *
4567 * *
4568 ************************************************************************/
4569
4570static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004571 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004572static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004573 xmlNodePtr elem,
4574 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00004575static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004576 xmlNodePtr elem,
4577 xmlSchemaElementPtr elemDecl,
4578 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004579
4580/**
4581 * xmlSchemaRegisterAttributes:
4582 * @ctxt: a schema validation context
4583 * @attrs: a list of attributes
4584 *
4585 * Register the list of attributes as the set to be validated on that element
4586 *
4587 * Returns -1 in case of error, 0 otherwise
4588 */
4589static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004590xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
4591{
Daniel Veillard4255d502002-04-16 15:50:10 +00004592 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004593 if ((attrs->ns != NULL) &&
4594 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
4595 attrs = attrs->next;
4596 continue;
4597 }
4598 if (ctxt->attrNr >= ctxt->attrMax) {
4599 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00004600
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004601 ctxt->attrMax *= 2;
4602 tmp = (xmlSchemaAttrStatePtr)
4603 xmlRealloc(ctxt->attr, ctxt->attrMax *
4604 sizeof(xmlSchemaAttrState));
4605 if (tmp == NULL) {
4606 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
4607 ctxt->attrMax /= 2;
4608 return (-1);
4609 }
4610 ctxt->attr = tmp;
4611 }
4612 ctxt->attr[ctxt->attrNr].attr = attrs;
4613 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
4614 ctxt->attrNr++;
4615 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004616 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004617 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004618}
4619
4620/**
4621 * xmlSchemaCheckAttributes:
4622 * @ctxt: a schema validation context
4623 * @node: the node carrying it.
4624 *
4625 * Check that the registered set of attributes on the current node
4626 * has been properly validated.
4627 *
4628 * Returns 0 if validity constraints are met, 1 otherwise.
4629 */
4630static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004631xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
4632{
Daniel Veillard4255d502002-04-16 15:50:10 +00004633 int ret = 0;
4634 int i;
4635
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004636 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
4637 if (ctxt->attr[i].attr == NULL)
4638 break;
4639 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
4640 ret = 1;
4641 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
4642 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004643 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004644 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004645}
4646
4647/**
4648 * xmlSchemaValidateSimpleContent:
4649 * @ctxt: a schema validation context
4650 * @elem: an element
4651 * @type: the type declaration
4652 *
4653 * Validate the content of an element expected to be a simple type
4654 *
4655 * Returns 0 if the element is schemas valid, a positive error code
4656 * number otherwise and -1 in case of internal or API error.
4657 */
4658static int
4659xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004660 xmlNodePtr node ATTRIBUTE_UNUSED)
4661{
Daniel Veillard4255d502002-04-16 15:50:10 +00004662 xmlNodePtr child;
4663 xmlSchemaTypePtr type, base;
4664 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00004665 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004666
4667 child = ctxt->node;
4668 type = ctxt->type;
4669
4670 /*
4671 * Validation Rule: Element Locally Valid (Type): 3.1.3
4672 */
4673 value = xmlNodeGetContent(child);
4674 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
4675 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004676 case XML_SCHEMA_TYPE_RESTRICTION:{
4677 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00004678
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004679 base = type->baseType;
4680 if (base != NULL) {
4681 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4682 } else {
4683 TODO}
4684 if (ret == 0) {
4685 facet = type->facets;
4686 ret =
4687 xmlSchemaValidateFacets(ctxt, base, facet, value);
4688 }
4689 break;
4690 }
4691 default:
4692 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00004693 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004694 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00004695
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004696 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004697}
4698
4699/**
4700 * xmlSchemaValidateCheckNodeList
4701 * @nodelist: the list of nodes
4702 *
4703 * Check the node list is only made of text nodes and entities pointing
4704 * to text nodes
4705 *
4706 * Returns 1 if true, 0 if false and -1 in case of error
4707 */
4708static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004709xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
4710{
Daniel Veillard4255d502002-04-16 15:50:10 +00004711 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004712 if (nodelist->type == XML_ENTITY_REF_NODE) {
4713 TODO /* implement recursion in the entity content */
4714 }
4715 if ((nodelist->type != XML_TEXT_NODE) &&
4716 (nodelist->type != XML_COMMENT_NODE) &&
4717 (nodelist->type != XML_PI_NODE) &&
4718 (nodelist->type != XML_PI_NODE)) {
4719 return (0);
4720 }
4721 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004722 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004723 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004724}
4725
4726/**
4727 * xmlSchemaSkipIgnored:
4728 * @ctxt: a schema validation context
4729 * @type: the current type context
4730 * @node: the top node.
4731 *
4732 * Skip ignorable nodes in that context
4733 *
4734 * Returns the new sibling
4735 * number otherwise and -1 in case of internal or API error.
4736 */
4737static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00004738xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004739 xmlSchemaTypePtr type, xmlNodePtr node)
4740{
Daniel Veillard4255d502002-04-16 15:50:10 +00004741 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004742
Daniel Veillard4255d502002-04-16 15:50:10 +00004743 /*
4744 * TODO complete and handle entities
4745 */
4746 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004747 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00004748 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004749 ((node->type == XML_COMMENT_NODE) ||
4750 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
4751 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
4752 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
4753 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004754 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004755 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004756}
4757
4758/**
4759 * xmlSchemaValidateCallback:
4760 * @ctxt: a schema validation context
4761 * @name: the name of the element detected (might be NULL)
4762 * @type: the type
4763 *
4764 * A transition has been made in the automata associated to an element
4765 * content model
4766 */
4767static void
4768xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004769 const xmlChar * name ATTRIBUTE_UNUSED,
4770 xmlSchemaTypePtr type, xmlNodePtr node)
4771{
Daniel Veillard4255d502002-04-16 15:50:10 +00004772 xmlSchemaTypePtr oldtype = ctxt->type;
4773 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004774
Daniel Veillard4255d502002-04-16 15:50:10 +00004775#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00004776 xmlGenericError(xmlGenericErrorContext,
4777 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004778 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004779#endif
4780 ctxt->type = type;
4781 ctxt->node = node;
4782 xmlSchemaValidateContent(ctxt, node);
4783 ctxt->type = oldtype;
4784 ctxt->node = oldnode;
4785}
4786
4787
4788#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004789
Daniel Veillard4255d502002-04-16 15:50:10 +00004790/**
4791 * xmlSchemaValidateSimpleRestrictionType:
4792 * @ctxt: a schema validation context
4793 * @node: the top node.
4794 *
4795 * Validate the content of a restriction type.
4796 *
4797 * Returns 0 if the element is schemas valid, a positive error code
4798 * number otherwise and -1 in case of internal or API error.
4799 */
4800static int
4801xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
4802 xmlNodePtr node)
4803{
4804 xmlNodePtr child;
4805 xmlSchemaTypePtr type;
4806 int ret;
4807
4808 child = ctxt->node;
4809 type = ctxt->type;
4810
4811 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004812 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004813 return (-1);
4814 }
4815 /*
4816 * Only text and text based entities references shall be found there
4817 */
4818 ret = xmlSchemaValidateCheckNodeList(child);
4819 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004820 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004821 return (-1);
4822 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004823 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 +00004824 return (-1);
4825 }
4826 ctxt->type = type->subtypes;
4827 xmlSchemaValidateContent(ctxt, node);
4828 ctxt->type = type;
4829 return (ret);
4830}
4831#endif
4832
4833/**
4834 * xmlSchemaValidateSimpleType:
4835 * @ctxt: a schema validation context
4836 * @node: the top node.
4837 *
4838 * Validate the content of an simple type.
4839 *
4840 * Returns 0 if the element is schemas valid, a positive error code
4841 * number otherwise and -1 in case of internal or API error.
4842 */
4843static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004844xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
4845{
Daniel Veillard4255d502002-04-16 15:50:10 +00004846 xmlNodePtr child;
4847 xmlSchemaTypePtr type;
4848 xmlAttrPtr attr;
4849 int ret;
4850
4851 child = ctxt->node;
4852 type = ctxt->type;
4853
4854 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004855 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
4856 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004857 }
4858 /*
4859 * Only text and text based entities references shall be found there
4860 */
4861 ret = xmlSchemaValidateCheckNodeList(child);
4862 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004863 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
4864 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004865 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004866 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
4867 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004868 }
4869 /*
4870 * Validation Rule: Element Locally Valid (Type): 3.1.1
4871 */
4872 attr = node->properties;
4873 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004874 if ((attr->ns == NULL) ||
4875 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
4876 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
4877 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
4878 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
4879 (!xmlStrEqual
4880 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
4881 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
4882 return (ctxt->err);
4883 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004884 }
4885
4886 ctxt->type = type->subtypes;
4887 ret = xmlSchemaValidateSimpleContent(ctxt, node);
4888 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004889 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004890}
4891
4892/**
4893 * xmlSchemaValidateElementType:
4894 * @ctxt: a schema validation context
4895 * @node: the top node.
4896 *
4897 * Validate the content of an element type.
4898 * Validation Rule: Element Locally Valid (Complex Type)
4899 *
4900 * Returns 0 if the element is schemas valid, a positive error code
4901 * number otherwise and -1 in case of internal or API error.
4902 */
4903static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004904xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
4905{
Daniel Veillard4255d502002-04-16 15:50:10 +00004906 xmlNodePtr child;
4907 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004908 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00004909 xmlSchemaElementPtr decl;
4910 int ret, attrBase;
4911
4912 oldregexp = ctxt->regexp;
4913
4914 child = ctxt->node;
4915 type = ctxt->type;
4916
4917 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004918 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
4919 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004920 }
4921 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004922 if (type->minOccurs > 0) {
4923 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
4924 }
4925 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00004926 }
4927
4928 /*
4929 * Verify the element matches
4930 */
4931 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004932 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
4933 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00004934 }
4935 /*
4936 * Verify the attributes
4937 */
4938 attrBase = ctxt->attrBase;
4939 ctxt->attrBase = ctxt->attrNr;
4940 xmlSchemaRegisterAttributes(ctxt, child->properties);
4941 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
4942 /*
4943 * Verify the element content recursively
4944 */
4945 decl = (xmlSchemaElementPtr) type;
4946 oldregexp = ctxt->regexp;
4947 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004948 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
4949 (xmlRegExecCallbacks)
4950 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004951#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004952 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004953#endif
4954 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004955 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
4956 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00004957
4958 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004959 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004960#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004961 xmlGenericError(xmlGenericErrorContext,
4962 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004963#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004964 if (ret == 0) {
4965 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
4966 } else if (ret < 0) {
4967 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004968#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004969 } else {
4970 xmlGenericError(xmlGenericErrorContext,
4971 "Element %s content check succeeded\n",
4972 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004973
4974#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004975 }
4976 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00004977 }
4978 /*
4979 * Verify that all attributes were Schemas-validated
4980 */
4981 xmlSchemaCheckAttributes(ctxt, node);
4982 ctxt->attrNr = ctxt->attrBase;
4983 ctxt->attrBase = attrBase;
4984
4985 ctxt->regexp = oldregexp;
4986
4987 ctxt->node = child;
4988 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004989 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00004990}
4991
4992/**
4993 * xmlSchemaValidateBasicType:
4994 * @ctxt: a schema validation context
4995 * @node: the top node.
4996 *
4997 * Validate the content of an element expected to be a basic type type
4998 *
4999 * Returns 0 if the element is schemas valid, a positive error code
5000 * number otherwise and -1 in case of internal or API error.
5001 */
5002static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005003xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5004{
Daniel Veillard4255d502002-04-16 15:50:10 +00005005 int ret;
5006 xmlNodePtr child, cur;
5007 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005008 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005009
5010 child = ctxt->node;
5011 type = ctxt->type;
5012
5013 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005014 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5015 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005016 }
5017 /*
5018 * First check the content model of the node.
5019 */
5020 cur = child;
5021 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005022 switch (cur->type) {
5023 case XML_TEXT_NODE:
5024 case XML_CDATA_SECTION_NODE:
5025 case XML_PI_NODE:
5026 case XML_COMMENT_NODE:
5027 case XML_XINCLUDE_START:
5028 case XML_XINCLUDE_END:
5029 break;
5030 case XML_ENTITY_REF_NODE:
5031 case XML_ENTITY_NODE:
5032 TODO break;
5033 case XML_ELEMENT_NODE:
5034 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5035 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005036 case XML_ATTRIBUTE_NODE:
5037 case XML_DOCUMENT_NODE:
5038 case XML_DOCUMENT_TYPE_NODE:
5039 case XML_DOCUMENT_FRAG_NODE:
5040 case XML_NOTATION_NODE:
5041 case XML_HTML_DOCUMENT_NODE:
5042 case XML_DTD_NODE:
5043 case XML_ELEMENT_DECL:
5044 case XML_ATTRIBUTE_DECL:
5045 case XML_ENTITY_DECL:
5046 case XML_NAMESPACE_DECL:
5047#ifdef LIBXML_DOCB_ENABLED
5048 case XML_DOCB_DOCUMENT_NODE:
5049#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005050 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5051 return (ctxt->err);
5052 }
5053 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005054 }
5055 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005056 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005057 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005058 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005059
5060 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005061 xmlSchemaFreeValue(ctxt->value);
5062 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005063 }
5064 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5065 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005066 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005067 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005068 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 +00005069 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005070 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005071}
5072
5073/**
5074 * xmlSchemaValidateComplexType:
5075 * @ctxt: a schema validation context
5076 * @node: the top node.
5077 *
5078 * Validate the content of an element expected to be a complex type type
5079 * xmlschema-1.html#cvc-complex-type
5080 * Validation Rule: Element Locally Valid (Complex Type)
5081 *
5082 * Returns 0 if the element is schemas valid, a positive error code
5083 * number otherwise and -1 in case of internal or API error.
5084 */
5085static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005086xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5087{
Daniel Veillard4255d502002-04-16 15:50:10 +00005088 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005089 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005090 int ret;
5091
5092 child = ctxt->node;
5093 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005094 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005095
Daniel Veillard4255d502002-04-16 15:50:10 +00005096 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005097 case XML_SCHEMA_CONTENT_EMPTY:
5098 if (child != NULL) {
5099 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5100 }
5101 if (type->attributes != NULL) {
5102 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5103 }
5104 subtype = type->subtypes;
5105 while (subtype != NULL) {
5106 ctxt->type = subtype;
5107 xmlSchemaValidateComplexType(ctxt, node);
5108 subtype = subtype->next;
5109 }
5110 break;
5111 case XML_SCHEMA_CONTENT_ELEMENTS:
5112 case XML_SCHEMA_CONTENT_MIXED:
5113 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5114 /*
5115 * Skip ignorable nodes in that context
5116 */
5117 child = xmlSchemaSkipIgnored(ctxt, type, child);
5118 while (child != NULL) {
5119 if (child->type == XML_ELEMENT_NODE) {
5120 ret = xmlRegExecPushString(ctxt->regexp,
5121 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005122#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005123 if (ret < 0)
5124 xmlGenericError(xmlGenericErrorContext,
5125 " --> %s Error\n", child->name);
5126 else
5127 xmlGenericError(xmlGenericErrorContext,
5128 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005129#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005130 }
5131 child = child->next;
5132 /*
5133 * Skip ignorable nodes in that context
5134 */
5135 child = xmlSchemaSkipIgnored(ctxt, type, child);
5136 }
5137 break;
5138 case XML_SCHEMA_CONTENT_BASIC:{
5139 if (type->subtypes != NULL) {
5140 ctxt->type = type->subtypes;
5141 xmlSchemaValidateComplexType(ctxt, node);
5142 }
5143 if (type->baseType != NULL) {
5144 ctxt->type = type->baseType;
5145 xmlSchemaValidateBasicType(ctxt, node);
5146 }
5147 if (type->attributes != NULL) {
5148 xmlSchemaValidateAttributes(ctxt, node,
5149 type->attributes);
5150 }
5151 ctxt->type = type;
5152 break;
5153 }
5154 default:
5155 TODO xmlGenericError(xmlGenericErrorContext,
5156 "unimplemented content type %d\n",
5157 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005158 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005159 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005160}
5161
5162/**
5163 * xmlSchemaValidateContent:
5164 * @ctxt: a schema validation context
5165 * @elem: an element
5166 * @type: the type declaration
5167 *
5168 * Validate the content of an element against the type.
5169 *
5170 * Returns 0 if the element is schemas valid, a positive error code
5171 * number otherwise and -1 in case of internal or API error.
5172 */
5173static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005174xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5175{
Daniel Veillard4255d502002-04-16 15:50:10 +00005176 xmlNodePtr child;
5177 xmlSchemaTypePtr type;
5178
5179 child = ctxt->node;
5180 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005181 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005182
Daniel Veillarde19fc232002-04-22 16:01:24 +00005183 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005184 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00005185
Daniel Veillard4255d502002-04-16 15:50:10 +00005186 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005187 case XML_SCHEMA_TYPE_ANY:
5188 /* Any type will do it, fine */
5189 TODO /* handle recursivity */
5190 break;
5191 case XML_SCHEMA_TYPE_COMPLEX:
5192 xmlSchemaValidateComplexType(ctxt, node);
5193 break;
5194 case XML_SCHEMA_TYPE_ELEMENT:{
5195 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5196
5197 /*
5198 * Handle element reference here
5199 */
5200 if (decl->ref != NULL) {
5201 if (decl->refDecl == NULL) {
5202 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
5203 return (-1);
5204 }
5205 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5206 decl = decl->refDecl;
5207 }
5208 xmlSchemaValidateElementType(ctxt, node);
5209 ctxt->type = type;
5210 break;
5211 }
5212 case XML_SCHEMA_TYPE_BASIC:
5213 xmlSchemaValidateBasicType(ctxt, node);
5214 break;
5215 case XML_SCHEMA_TYPE_FACET:
5216 TODO break;
5217 case XML_SCHEMA_TYPE_SIMPLE:
5218 xmlSchemaValidateSimpleType(ctxt, node);
5219 break;
5220 case XML_SCHEMA_TYPE_SEQUENCE:
5221 TODO break;
5222 case XML_SCHEMA_TYPE_CHOICE:
5223 TODO break;
5224 case XML_SCHEMA_TYPE_ALL:
5225 TODO break;
5226 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5227 TODO break;
5228 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5229 TODO break;
5230 case XML_SCHEMA_TYPE_UR:
5231 TODO break;
5232 case XML_SCHEMA_TYPE_RESTRICTION:
5233 /*xmlSchemaValidateRestrictionType(ctxt, node); */
5234 TODO break;
5235 case XML_SCHEMA_TYPE_EXTENSION:
5236 TODO break;
5237 case XML_SCHEMA_TYPE_ATTRIBUTE:
5238 TODO break;
5239 case XML_SCHEMA_TYPE_GROUP:
5240 TODO break;
5241 case XML_SCHEMA_TYPE_NOTATION:
5242 TODO break;
5243 case XML_SCHEMA_TYPE_LIST:
5244 TODO break;
5245 case XML_SCHEMA_TYPE_UNION:
5246 TODO break;
5247 case XML_SCHEMA_FACET_MININCLUSIVE:
5248 TODO break;
5249 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5250 TODO break;
5251 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5252 TODO break;
5253 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5254 TODO break;
5255 case XML_SCHEMA_FACET_TOTALDIGITS:
5256 TODO break;
5257 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5258 TODO break;
5259 case XML_SCHEMA_FACET_PATTERN:
5260 TODO break;
5261 case XML_SCHEMA_FACET_ENUMERATION:
5262 TODO break;
5263 case XML_SCHEMA_FACET_WHITESPACE:
5264 TODO break;
5265 case XML_SCHEMA_FACET_LENGTH:
5266 TODO break;
5267 case XML_SCHEMA_FACET_MAXLENGTH:
5268 TODO break;
5269 case XML_SCHEMA_FACET_MINLENGTH:
5270 TODO break;
5271 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5272 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00005273 }
5274 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5275
5276 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005277 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005278 ctxt->node = ctxt->node->next;
5279 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005280 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005281}
5282
5283/**
5284 * xmlSchemaValidateType:
5285 * @ctxt: a schema validation context
5286 * @elem: an element
5287 * @type: the list of type declarations
5288 *
5289 * Validate the content of an element against the types.
5290 *
5291 * Returns 0 if the element is schemas valid, a positive error code
5292 * number otherwise and -1 in case of internal or API error.
5293 */
5294static int
5295xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005296 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
5297{
Daniel Veillard4255d502002-04-16 15:50:10 +00005298 xmlChar *nil;
5299
Daniel Veillard2db8c122003-07-08 12:16:59 +00005300 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005301 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00005302
Daniel Veillard4255d502002-04-16 15:50:10 +00005303 /*
5304 * 3.3.4 : 2
5305 */
5306 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005307 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
5308 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005309 }
5310 /*
5311 * 3.3.4: 3
5312 */
5313 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5314 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005315 /* 3.3.4: 3.2 */
5316 if (xmlStrEqual(nil, BAD_CAST "true")) {
5317 if (elem->children != NULL) {
5318 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
5319 return (ctxt->err);
5320 }
5321 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
5322 (elemDecl->value != NULL)) {
5323 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
5324 return (ctxt->err);
5325 }
5326 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005327 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005328 /* 3.3.4: 3.1 */
5329 if (nil != NULL) {
5330 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
5331 xmlFree(nil);
5332 return (ctxt->err);
5333 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005334 }
5335
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005336 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00005337
5338 ctxt->type = elemDecl->subtypes;
5339 ctxt->node = elem->children;
5340 xmlSchemaValidateContent(ctxt, elem);
5341 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005342
5343 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005344}
5345
5346
5347/**
5348 * xmlSchemaValidateAttributes:
5349 * @ctxt: a schema validation context
5350 * @elem: an element
5351 * @attributes: the list of attribute declarations
5352 *
5353 * Validate the attributes of an element.
5354 *
5355 * Returns 0 if the element is schemas valid, a positive error code
5356 * number otherwise and -1 in case of internal or API error.
5357 */
5358static int
5359xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005360 xmlSchemaAttributePtr attributes)
5361{
Daniel Veillard4255d502002-04-16 15:50:10 +00005362 int i, ret;
5363 xmlAttrPtr attr;
5364 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005365 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005366
5367 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005368 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005369 while (attributes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005370 /*
5371 * Handle attribute groups
5372 */
5373 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5374 group = (xmlSchemaAttributeGroupPtr) attributes;
5375 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
5376 attributes = group->next;
5377 continue;
5378 }
5379 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5380 attr = ctxt->attr[i].attr;
5381 if (attr == NULL)
5382 continue;
5383 if (attributes->ref != NULL) {
5384 if (!xmlStrEqual(attr->name, attributes->ref))
5385 continue;
5386 if (attr->ns != NULL) {
5387 if ((attributes->refNs == NULL) ||
5388 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
5389 continue;
5390 } else if (attributes->refNs != NULL) {
5391 continue;
5392 }
5393 } else {
5394 if (!xmlStrEqual(attr->name, attributes->name))
5395 continue;
5396 /*
5397 * TODO: handle the mess about namespaces here.
5398 */
5399 if ((attr->ns != NULL) /* || (attributes->ns != NULL) */ ) {
5400 TODO}
5401 }
5402 ctxt->cur = (xmlNodePtr) attributes;
5403 if (attributes->subtypes == NULL) {
5404 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
5405 continue;
5406 }
5407 value = xmlNodeListGetString(elem->doc, attr->children, 1);
5408 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
5409 value);
5410 if (ret != 0) {
5411 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
5412 } else {
5413 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
5414 }
5415 if (value != NULL) {
5416 xmlFree(value);
5417 }
5418 }
5419 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005420 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005421 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005422}
5423
5424/**
5425 * xmlSchemaValidateElement:
5426 * @ctxt: a schema validation context
5427 * @elem: an element
5428 *
5429 * Validate an element in a tree
5430 *
5431 * Returns 0 if the element is schemas valid, a positive error code
5432 * number otherwise and -1 in case of internal or API error.
5433 */
5434static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005435xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
5436{
Daniel Veillard4255d502002-04-16 15:50:10 +00005437 xmlSchemaElementPtr elemDecl;
5438 int ret, attrBase;
5439
5440 if (elem->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005441 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5442 elem->name, elem->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005443 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005444 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5445 elem->name, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005446 /*
5447 * 3.3.4 : 1
5448 */
5449 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005450 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
5451 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005452 }
5453 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005454 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
5455 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005456 }
5457 /*
5458 * Verify the attributes
5459 */
5460 attrBase = ctxt->attrBase;
5461 ctxt->attrBase = ctxt->attrNr;
5462 xmlSchemaRegisterAttributes(ctxt, elem->properties);
5463 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5464 /*
5465 * Verify the element content recursively
5466 */
5467 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005468 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
5469 (xmlRegExecCallbacks)
5470 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005471#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005472 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005473#endif
5474 }
5475 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005476 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005477 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005478#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005479 xmlGenericError(xmlGenericErrorContext,
5480 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005481#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005482 if (ret == 0) {
5483 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
5484 } else if (ret < 0) {
5485 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005486#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005487 } else {
5488 xmlGenericError(xmlGenericErrorContext,
5489 "Element %s content check succeeded\n",
5490 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005491
5492#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005493 }
5494 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005495 }
5496 /*
5497 * Verify that all attributes were Schemas-validated
5498 */
5499 xmlSchemaCheckAttributes(ctxt, elem);
5500 ctxt->attrNr = ctxt->attrBase;
5501 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005502
5503 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005504}
5505
5506/**
5507 * xmlSchemaValidateDocument:
5508 * @ctxt: a schema validation context
5509 * @doc: a parsed document tree
5510 *
5511 * Validate a document tree in memory.
5512 *
5513 * Returns 0 if the document is schemas valid, a positive error code
5514 * number otherwise and -1 in case of internal or API error.
5515 */
5516static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005517xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
5518{
Daniel Veillard4255d502002-04-16 15:50:10 +00005519 xmlNodePtr root;
5520 xmlSchemaElementPtr elemDecl;
5521
5522 root = xmlDocGetRootElement(doc);
5523 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005524 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
5525 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005526 }
5527 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005528 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5529 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005530 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005531 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5532 root->name, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005533 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005534 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005535 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005536 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005537 }
5538 /*
5539 * Okay, start the recursive validation
5540 */
5541 xmlSchemaValidateElement(ctxt, root);
5542
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005543 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005544}
5545
5546/************************************************************************
5547 * *
5548 * SAX Validation code *
5549 * *
5550 ************************************************************************/
5551
5552/************************************************************************
5553 * *
5554 * Validation interfaces *
5555 * *
5556 ************************************************************************/
5557
5558/**
5559 * xmlSchemaNewValidCtxt:
5560 * @schema: a precompiled XML Schemas
5561 *
5562 * Create an XML Schemas validation context based on the given schema
5563 *
5564 * Returns the validation context or NULL in case of error
5565 */
5566xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005567xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
5568{
Daniel Veillard4255d502002-04-16 15:50:10 +00005569 xmlSchemaValidCtxtPtr ret;
5570
5571 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
5572 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005573 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005574 return (NULL);
5575 }
5576 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
5577 ret->schema = schema;
5578 ret->attrNr = 0;
5579 ret->attrMax = 10;
5580 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005581 sizeof
5582 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00005583 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005584 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
5585 free(ret);
5586 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005587 }
5588 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
5589 return (ret);
5590}
5591
5592/**
5593 * xmlSchemaFreeValidCtxt:
5594 * @ctxt: the schema validation context
5595 *
5596 * Free the resources associated to the schema validation context
5597 */
5598void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005599xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
5600{
Daniel Veillard4255d502002-04-16 15:50:10 +00005601 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005602 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005603 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005604 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00005605 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005606 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005607 xmlFree(ctxt);
5608}
5609
5610/**
5611 * xmlSchemaSetValidErrors:
5612 * @ctxt: a schema validation context
5613 * @err: the error function
5614 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00005615 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00005616 *
5617 * Set the error and warning callback informations
5618 */
5619void
5620xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005621 xmlSchemaValidityErrorFunc err,
5622 xmlSchemaValidityWarningFunc warn, void *ctx)
5623{
Daniel Veillard4255d502002-04-16 15:50:10 +00005624 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005625 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005626 ctxt->error = err;
5627 ctxt->warning = warn;
5628 ctxt->userData = ctx;
5629}
5630
5631/**
5632 * xmlSchemaValidateDoc:
5633 * @ctxt: a schema validation context
5634 * @doc: a parsed document tree
5635 *
5636 * Validate a document tree in memory.
5637 *
5638 * Returns 0 if the document is schemas valid, a positive error code
5639 * number otherwise and -1 in case of internal or API error.
5640 */
5641int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005642xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
5643{
Daniel Veillard4255d502002-04-16 15:50:10 +00005644 int ret;
5645
5646 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005647 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005648
5649 ctxt->doc = doc;
5650 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005651 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005652}
5653
5654/**
5655 * xmlSchemaValidateStream:
5656 * @ctxt: a schema validation context
5657 * @input: the input to use for reading the data
5658 * @enc: an optional encoding information
5659 * @sax: a SAX handler for the resulting events
5660 * @user_data: the context to provide to the SAX handler.
5661 *
5662 * Validate a document tree in memory.
5663 *
5664 * Returns 0 if the document is schemas valid, a positive error code
5665 * number otherwise and -1 in case of internal or API error.
5666 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005667int
Daniel Veillard4255d502002-04-16 15:50:10 +00005668xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005669 xmlParserInputBufferPtr input, xmlCharEncoding enc,
5670 xmlSAXHandlerPtr sax, void *user_data)
5671{
Daniel Veillard4255d502002-04-16 15:50:10 +00005672 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005673 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005674 ctxt->input = input;
5675 ctxt->enc = enc;
5676 ctxt->sax = sax;
5677 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005678 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005679}
5680
5681#endif /* LIBXML_SCHEMAS_ENABLED */