BRANCH release for 2.5.x critical patches
[baserock-morphs:libxml2.git] / xmlschemas.c
1 /*
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>
20 #include <libxml/uri.h>
21
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
28 /* #define DEBUG 1 */
29 /* #define DEBUG_CONTENT 1 */
30 /* #define DEBUG_TYPE 1 */
31 /* #define DEBUG_CONTENT_REGEXP 1 */
32 /* #define DEBUG_AUTOMATA 1 */
33
34 #define UNBOUNDED (1 << 30)
35 #define TODO                                                            \
36     xmlGenericError(xmlGenericErrorContext,                             \
37             "Unimplemented block at %s:%d\n",                           \
38             __FILE__, __LINE__);
39
40 #define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
41
42 /*
43  * The XML Schemas namespaces
44  */
45 static const xmlChar *xmlSchemaNs = (const xmlChar *)
46     "http://www.w3.org/2001/XMLSchema";
47
48 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
49     "http://www.w3.org/2001/XMLSchema-instance";
50
51 #define IS_SCHEMA(node, type)                                           \
52    ((node != NULL) && (node->ns != NULL) &&                             \
53     (xmlStrEqual(node->name, (const xmlChar *) type)) &&                \
54     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
55
56 #define XML_SCHEMAS_PARSE_ERROR         1
57
58 struct _xmlSchemaParserCtxt {
59     void *userData;                     /* user specific data block */
60     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
61     xmlSchemaValidityWarningFunc warning;/* the callback in case of warning */
62     xmlSchemaValidError err;
63     int                 nberrors;
64
65     xmlSchemaPtr       schema;        /* The schema in use */
66     xmlChar           *container;     /* the current element, group, ... */
67     int counter;
68
69     xmlChar           *URL;
70     xmlDocPtr          doc;
71
72     const char     *buffer;
73     int               size;
74
75     /*
76      * Used to build complex element content models
77      */
78     xmlAutomataPtr     am;
79     xmlAutomataStatePtr start;
80     xmlAutomataStatePtr end;
81     xmlAutomataStatePtr state;
82 };
83
84
85 #define XML_SCHEMAS_ATTR_UNKNOWN 1
86 #define XML_SCHEMAS_ATTR_CHECKED 2
87
88 typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
89 typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
90 struct _xmlSchemaAttrState {
91     xmlAttrPtr       attr;
92     int              state;
93 };
94
95 /**
96  * xmlSchemaValidCtxt:
97  *
98  * A Schemas validation context
99  */
100
101 struct _xmlSchemaValidCtxt {
102     void *userData;                     /* user specific data block */
103     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
104     xmlSchemaValidityWarningFunc warning;/* the callback in case of warning */
105
106     xmlSchemaPtr            schema;        /* The schema in use */
107     xmlDocPtr               doc;
108     xmlParserInputBufferPtr input;
109     xmlCharEncoding         enc;
110     xmlSAXHandlerPtr        sax;
111     void                   *user_data;
112
113     xmlDocPtr               myDoc;
114     int                     err;
115     int                     nberrors;
116
117     xmlNodePtr              node;
118     xmlNodePtr              cur;
119     xmlSchemaTypePtr        type;
120
121     xmlRegExecCtxtPtr       regexp;
122     xmlSchemaValPtr         value;
123
124     int                     attrNr;
125     int                     attrBase;
126     int                     attrMax;
127     xmlSchemaAttrStatePtr   attr;
128 };
129
130
131 /************************************************************************
132  *                                                                      *
133  *                      Some predeclarations                            *
134  *                                                                      *
135  ************************************************************************/
136 static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt, 
137                              xmlSchemaTypePtr type,
138                              xmlChar *value);
139
140 /************************************************************************
141  *                                                                      *
142  *                      Allocation functions                            *
143  *                                                                      *
144  ************************************************************************/
145
146 /**
147  * xmlSchemaNewSchema:
148  * @ctxt:  a schema validation context (optional)
149  *
150  * Allocate a new Schema structure.
151  *
152  * Returns the newly allocated structure or NULL in case or error
153  */
154 static xmlSchemaPtr
155 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
156 {
157     xmlSchemaPtr ret;
158
159     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
160     if (ret == NULL) {
161         ctxt->nberrors++;
162         if ((ctxt != NULL) && (ctxt->error != NULL))
163             ctxt->error(ctxt->userData, "Out of memory\n");
164         return (NULL);
165     }
166     memset(ret, 0, sizeof(xmlSchema));
167
168     return (ret);
169 }
170
171 /**
172  * xmlSchemaNewFacet:
173  *
174  * Allocate a new Facet structure.
175  *
176  * Returns the newly allocated structure or NULL in case or error
177  */
178 xmlSchemaFacetPtr
179 xmlSchemaNewFacet(void)
180 {
181     xmlSchemaFacetPtr ret;
182
183     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
184     if (ret == NULL) {
185         return (NULL);
186     }
187     memset(ret, 0, sizeof(xmlSchemaFacet));
188
189     return (ret);
190 }
191
192 /**
193  * xmlSchemaNewAnnot:
194  * @ctxt:  a schema validation context (optional)
195  * @node:  a node
196  *
197  * Allocate a new annotation structure.
198  *
199  * Returns the newly allocated structure or NULL in case or error
200  */
201 static xmlSchemaAnnotPtr
202 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
203 {
204     xmlSchemaAnnotPtr ret;
205
206     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
207     if (ret == NULL) {
208         ctxt->nberrors++;
209         if ((ctxt != NULL) && (ctxt->error != NULL))
210             ctxt->error(ctxt->userData, "Out of memory\n");
211         return (NULL);
212     }
213     memset(ret, 0, sizeof(xmlSchemaAnnot));
214     ret->content = node;
215     return (ret);
216 }
217
218 /**
219  * xmlSchemaFreeAnnot:
220  * @annot:  a schema type structure
221  *
222  * Deallocate a annotation structure
223  */
224 static void
225 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
226 {
227     if (annot == NULL)
228         return;
229     xmlFree(annot);
230 }
231
232 /**
233  * xmlSchemaFreeNotation:
234  * @schema:  a schema notation structure
235  *
236  * Deallocate a Schema Notation structure.
237  */
238 static void
239 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
240 {
241     if (nota == NULL)
242         return;
243     if (nota->name != NULL)
244         xmlFree((xmlChar *) nota->name);
245     xmlFree(nota);
246 }
247
248 /**
249  * xmlSchemaFreeAttribute:
250  * @schema:  a schema attribute structure
251  *
252  * Deallocate a Schema Attribute structure.
253  */
254 static void
255 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
256 {
257     if (attr == NULL)
258         return;
259     if (attr->name != NULL)
260         xmlFree((xmlChar *) attr->name);
261     if (attr->ref != NULL)
262         xmlFree((xmlChar *) attr->ref);
263     if (attr->refNs != NULL)
264         xmlFree((xmlChar *) attr->refNs);
265     if (attr->typeName != NULL)
266         xmlFree((xmlChar *) attr->typeName);
267     if (attr->typeNs != NULL)
268         xmlFree((xmlChar *) attr->typeNs);
269     xmlFree(attr);
270 }
271
272 /**
273  * xmlSchemaFreeAttributeGroup:
274  * @schema:  a schema attribute group structure
275  *
276  * Deallocate a Schema Attribute Group structure.
277  */
278 static void
279 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
280 {
281     if (attr == NULL)
282         return;
283     if (attr->name != NULL)
284         xmlFree((xmlChar *) attr->name);
285     if (attr->ref != NULL)
286         xmlFree((xmlChar *) attr->ref);
287     if (attr->refNs != NULL)
288         xmlFree((xmlChar *) attr->refNs);
289     xmlFree(attr);
290 }
291
292 /**
293  * xmlSchemaFreeElement:
294  * @schema:  a schema element structure
295  *
296  * Deallocate a Schema Element structure.
297  */
298 static void
299 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
300 {
301     if (elem == NULL)
302         return;
303     if (elem->name != NULL)
304         xmlFree((xmlChar *) elem->name);
305     if (elem->namedType != NULL)
306         xmlFree((xmlChar *) elem->namedType);
307     if (elem->namedTypeNs != NULL)
308         xmlFree((xmlChar *) elem->namedTypeNs);
309     if (elem->ref != NULL)
310         xmlFree((xmlChar *) elem->ref);
311     if (elem->refNs != NULL)
312         xmlFree((xmlChar *) elem->refNs);
313     if (elem->annot != NULL)
314         xmlSchemaFreeAnnot(elem->annot);
315     if (elem->contModel != NULL)
316         xmlRegFreeRegexp(elem->contModel);
317     xmlFree(elem);
318 }
319
320 /**
321  * xmlSchemaFreeFacet:
322  * @facet:  a schema facet structure
323  *
324  * Deallocate a Schema Facet structure.
325  */
326 void
327 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
328 {
329     if (facet == NULL)
330         return;
331     if (facet->value != NULL)
332         xmlFree((xmlChar *) facet->value);
333     if (facet->id != NULL)
334         xmlFree((xmlChar *) facet->id);
335     if (facet->val != NULL)
336         xmlSchemaFreeValue(facet->val);
337     if (facet->regexp != NULL)
338         xmlRegFreeRegexp(facet->regexp);
339     if (facet->annot != NULL)
340         xmlSchemaFreeAnnot(facet->annot);
341     xmlFree(facet);
342 }
343
344 /**
345  * xmlSchemaFreeType:
346  * @type:  a schema type structure
347  *
348  * Deallocate a Schema Type structure.
349  */
350 void
351 xmlSchemaFreeType(xmlSchemaTypePtr type)
352 {
353     if (type == NULL)
354         return;
355     if (type->name != NULL)
356         xmlFree((xmlChar *) type->name);
357     if (type->base != NULL)
358         xmlFree((xmlChar *) type->base);
359     if (type->baseNs != NULL)
360         xmlFree((xmlChar *) type->baseNs);
361     if (type->annot != NULL)
362         xmlSchemaFreeAnnot(type->annot);
363     if (type->facets != NULL) {
364         xmlSchemaFacetPtr facet, next;
365
366         facet = type->facets;
367         while (facet != NULL) {
368             next = facet->next;
369             xmlSchemaFreeFacet(facet);
370             facet = next;
371         }
372     }
373     xmlFree(type);
374 }
375
376 /**
377  * xmlSchemaFree:
378  * @schema:  a schema structure
379  *
380  * Deallocate a Schema structure.
381  */
382 void
383 xmlSchemaFree(xmlSchemaPtr schema)
384 {
385     if (schema == NULL)
386         return;
387
388     if (schema->id != NULL)
389         xmlFree((xmlChar *) schema->id);
390     if (schema->targetNamespace != NULL)
391         xmlFree((xmlChar *) schema->targetNamespace);
392     if (schema->name != NULL)
393         xmlFree((xmlChar *) schema->name);
394     if (schema->notaDecl != NULL)
395         xmlHashFree(schema->notaDecl,
396                     (xmlHashDeallocator) xmlSchemaFreeNotation);
397     if (schema->attrDecl != NULL)
398         xmlHashFree(schema->attrDecl,
399                     (xmlHashDeallocator) xmlSchemaFreeAttribute);
400     if (schema->attrgrpDecl != NULL)
401         xmlHashFree(schema->attrgrpDecl,
402                     (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
403     if (schema->elemDecl != NULL)
404         xmlHashFree(schema->elemDecl,
405                     (xmlHashDeallocator) xmlSchemaFreeElement);
406     if (schema->typeDecl != NULL)
407         xmlHashFree(schema->typeDecl,
408                     (xmlHashDeallocator) xmlSchemaFreeType);
409     if (schema->groupDecl != NULL)
410         xmlHashFree(schema->groupDecl,
411                     (xmlHashDeallocator) xmlSchemaFreeType);
412     if (schema->annot != NULL)
413         xmlSchemaFreeAnnot(schema->annot);
414     if (schema->doc != NULL)
415         xmlFreeDoc(schema->doc);
416
417     xmlFree(schema);
418 }
419
420 /************************************************************************
421  *                                                                      *
422  *                      Error functions                                 *
423  *                                                                      *
424  ************************************************************************/
425
426 /**
427  * xmlSchemaErrorContext:
428  * @ctxt:  the parsing context
429  * @schema:  the schema being built
430  * @node:  the node being processed
431  * @child:  the child being processed
432  *
433  * Dump a SchemaType structure
434  */
435 static void
436 xmlSchemaErrorContext(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
437                       xmlNodePtr node, xmlNodePtr child)
438 {
439     int line = 0;
440     const xmlChar *file = NULL;
441     const xmlChar *name = NULL;
442     const xmlChar *prefix = NULL;
443     const char *type = "error";
444
445     if ((ctxt == NULL) || (ctxt->error == NULL))
446         return;
447
448     if (child != NULL)
449         node = child;
450
451     if (node != NULL)  {
452         if ((node->type == XML_DOCUMENT_NODE) ||
453             (node->type == XML_HTML_DOCUMENT_NODE)) {
454             xmlDocPtr doc = (xmlDocPtr) node;
455
456             file = doc->URL;
457         } else {
458             /*
459              * Try to find contextual informations to report
460              */
461             if (node->type == XML_ELEMENT_NODE) {
462                 line = (long) node->content;
463             } else if ((node->prev != NULL) &&
464                        (node->prev->type == XML_ELEMENT_NODE)) {
465                 line = (long) node->prev->content;
466             } else if ((node->parent != NULL) &&
467                        (node->parent->type == XML_ELEMENT_NODE)) {
468                 line = (long) node->parent->content;
469             }
470             if ((node->doc != NULL) && (node->doc->URL != NULL))
471                 file = node->doc->URL;
472             if (node->name != NULL)
473                 name = node->name;
474             if ((node->type == XML_ELEMENT_NODE) && (node->ns != NULL) &&
475                 (node->ns->prefix != NULL))
476                 prefix = node->ns->prefix;
477         }
478     } 
479     
480     if (ctxt != NULL)
481         type = "compilation error";
482     else if (schema != NULL)
483         type = "runtime error";
484
485     if ((file != NULL) && (line != 0) && (name != NULL) && (prefix != NULL))
486         ctxt->error(ctxt->userData, "%s: file %s line %d element %s:%s\n",
487                 type, file, line, prefix, name);
488     else if ((file != NULL) && (line != 0) && (name != NULL))
489         ctxt->error(ctxt->userData, "%s: file %s line %d element %s\n",
490                 type, file, line, name);
491     else if ((file != NULL) && (name != NULL) && (prefix != NULL))
492         ctxt->error(ctxt->userData, "%s: file %s element %s:%s\n",
493                 type, file, prefix, name);
494     else if ((file != NULL) && (name != NULL))
495         ctxt->error(ctxt->userData, "%s: file %s element %s\n",
496                 type, file, name);
497     else if ((file != NULL) && (line != 0))
498         ctxt->error(ctxt->userData, "%s: file %s line %d\n", type, file, line);
499     else if (file != NULL)
500         ctxt->error(ctxt->userData, "%s: file %s\n", type, file);
501     else if ((name != NULL) && (prefix != NULL))
502         ctxt->error(ctxt->userData, "%s: element %s:%s\n", type, prefix, name);
503     else if (name != NULL)
504         ctxt->error(ctxt->userData, "%s: element %s\n", type, name);
505     else
506         ctxt->error(ctxt->userData, "%s\n", type);
507 }
508
509 /************************************************************************
510  *                                                                      *
511  *                      Debug functions                                 *
512  *                                                                      *
513  ************************************************************************/
514
515 /**
516  * xmlSchemaElementDump:
517  * @elem:  an element
518  * @output:  the file output
519  *
520  * Dump the element
521  */
522 static void
523 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
524                      const xmlChar *name ATTRIBUTE_UNUSED,
525                      const xmlChar *context ATTRIBUTE_UNUSED,
526                      const xmlChar *namespace ATTRIBUTE_UNUSED)
527 {
528     if (elem == NULL)
529         return;
530
531     fprintf(output, "Element ");
532     if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
533         fprintf(output, "toplevel ");
534     fprintf(output, ": %s ", elem->name);
535     if (namespace != NULL)
536         fprintf(output, "namespace '%s' ", namespace);
537     
538     if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
539         fprintf(output, "nillable ");
540     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
541         fprintf(output, "global ");
542     if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
543         fprintf(output, "default ");
544     if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
545         fprintf(output, "fixed ");
546     if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
547         fprintf(output, "abstract ");
548     if (elem->flags & XML_SCHEMAS_ELEM_REF)
549         fprintf(output, "ref '%s' ", elem->ref);
550     if (elem->id != NULL)
551         fprintf(output, "id '%s' ", elem->id);
552     fprintf(output, "\n");
553     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
554         fprintf(output, "  ");
555         if (elem->minOccurs != 1)
556             fprintf(output, "min: %d ", elem->minOccurs);
557         if (elem->maxOccurs >= UNBOUNDED)
558             fprintf(output, "max: unbounded\n");
559         else if (elem->maxOccurs != 1)
560             fprintf(output, "max: %d\n", elem->maxOccurs);
561         else
562             fprintf(output, "\n");
563     }
564     if (elem->namedType != NULL) {
565         fprintf(output, "  type: %s", elem->namedType);
566         if (elem->namedTypeNs != NULL)
567             fprintf(output, " ns %s\n", elem->namedTypeNs);
568         else
569             fprintf(output, "\n");
570     }
571     if (elem->substGroup != NULL) {
572         fprintf(output, "  substitutionGroup: %s", elem->substGroup);
573         if (elem->substGroupNs != NULL)
574             fprintf(output, " ns %s\n", elem->substGroupNs);
575         else
576             fprintf(output, "\n");
577     }
578     if (elem->value != NULL)
579         fprintf(output, "  default: %s", elem->value);
580 }
581
582 /**
583  * xmlSchemaAnnotDump:
584  * @output:  the file output
585  * @annot:  a annotation
586  *
587  * Dump the annotation
588  */
589 static void
590 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
591 {
592     xmlChar *content;
593
594     if (annot == NULL)
595         return;
596
597     content = xmlNodeGetContent(annot->content);
598     if (content != NULL) {
599         fprintf(output, "  Annot: %s\n", content);
600         xmlFree(content);
601     } else
602         fprintf(output, "  Annot: empty\n");
603 }
604
605 /**
606  * xmlSchemaTypeDump:
607  * @output:  the file output
608  * @type:  a type structure
609  *
610  * Dump a SchemaType structure
611  */
612 static void
613 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
614 {
615     if (type == NULL) {
616         fprintf(output, "Type: NULL\n");
617         return;
618     }
619     fprintf(output, "Type: ");
620     if (type->name != NULL)
621         fprintf(output, "%s, ", type->name);
622     else
623         fprintf(output, "no name");
624     switch (type->type) {
625         case XML_SCHEMA_TYPE_BASIC:
626             fprintf(output, "basic ");
627             break;
628         case XML_SCHEMA_TYPE_SIMPLE:
629             fprintf(output, "simple ");
630             break;
631         case XML_SCHEMA_TYPE_COMPLEX:
632             fprintf(output, "complex ");
633             break;
634         case XML_SCHEMA_TYPE_SEQUENCE:
635             fprintf(output, "sequence ");
636             break;
637         case XML_SCHEMA_TYPE_CHOICE:
638             fprintf(output, "choice ");
639             break;
640         case XML_SCHEMA_TYPE_ALL:
641             fprintf(output, "all ");
642             break;
643         case XML_SCHEMA_TYPE_UR:
644             fprintf(output, "ur ");
645             break;
646         case XML_SCHEMA_TYPE_RESTRICTION:
647             fprintf(output, "restriction ");
648             break;
649         case XML_SCHEMA_TYPE_EXTENSION:
650             fprintf(output, "extension ");
651             break;
652         default:
653             fprintf(output, "unknowntype%d ", type->type);
654             break;
655     }
656     if (type->base != NULL) {
657         fprintf(output, "base %s, ", type->base);
658     }
659     switch (type->contentType) {
660         case XML_SCHEMA_CONTENT_UNKNOWN:
661             fprintf(output, "unknown ");
662             break;
663         case XML_SCHEMA_CONTENT_EMPTY:
664             fprintf(output, "empty ");
665             break;
666         case XML_SCHEMA_CONTENT_ELEMENTS:
667             fprintf(output, "element ");
668             break;
669         case XML_SCHEMA_CONTENT_MIXED:
670             fprintf(output, "mixed ");
671             break;
672         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
673             fprintf(output, "mixed_or_elems ");
674             break;
675         case XML_SCHEMA_CONTENT_BASIC:
676             fprintf(output, "basic ");
677             break;
678         case XML_SCHEMA_CONTENT_SIMPLE:
679             fprintf(output, "simple ");
680             break;
681         case XML_SCHEMA_CONTENT_ANY:
682             fprintf(output, "any ");
683             break;
684     }
685     fprintf(output, "\n");
686     if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
687         fprintf(output, "  ");
688         if (type->minOccurs != 1)
689             fprintf(output, "min: %d ", type->minOccurs);
690         if (type->maxOccurs >= UNBOUNDED)
691             fprintf(output, "max: unbounded\n");
692         else if (type->maxOccurs != 1)
693             fprintf(output, "max: %d\n", type->maxOccurs);
694         else
695             fprintf(output, "\n");
696     }
697     if (type->annot != NULL)
698         xmlSchemaAnnotDump(output, type->annot);
699     if (type->subtypes != NULL) {
700         xmlSchemaTypePtr sub = type->subtypes;
701
702         fprintf(output, "  subtypes: ");
703         while (sub != NULL) {
704             fprintf(output, "%s ", sub->name);
705             sub = sub->next;
706         }
707         fprintf(output, "\n");
708     }
709
710 }
711
712 /**
713  * xmlSchemaDump:
714  * @output:  the file output
715  * @schema:  a schema structure
716  *
717  * Dump a Schema structure.
718  */
719 void
720 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
721 {
722     if (schema == NULL) {
723         fprintf(output, "Schemas: NULL\n");
724         return;
725     }
726     fprintf(output, "Schemas: ");
727     if (schema->name != NULL)
728         fprintf(output, "%s, ", schema->name);
729     else
730         fprintf(output, "no name, ");
731     if (schema->targetNamespace != NULL)
732         fprintf(output, "%s", (const char *) schema->targetNamespace);
733     else
734         fprintf(output, "no target namespace");
735     fprintf(output, "\n");
736     if (schema->annot != NULL)
737         xmlSchemaAnnotDump(output, schema->annot);
738
739     xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
740                 output);
741     xmlHashScanFull(schema->elemDecl,
742                     (xmlHashScannerFull) xmlSchemaElementDump, output);
743 }
744
745 /************************************************************************
746  *                                                                      *
747  *                      Parsing functions                               *
748  *                                                                      *
749  ************************************************************************/
750
751 /**
752  * xmlSchemaGetType:
753  * @schema:  the schemas context
754  * @name:  the type name
755  * @ns:  the type namespace
756  *
757  * Lookup a type in the schemas or the predefined types
758  *
759  * Returns the group definition or NULL if not found.
760  */
761 static xmlSchemaTypePtr
762 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
763                  const xmlChar * namespace) {
764     xmlSchemaTypePtr ret;
765
766     if (name == NULL)
767         return(NULL);
768     if (schema != NULL) {
769         ret = xmlHashLookup2(schema->typeDecl, name, namespace);
770         if (ret != NULL)
771             return(ret);
772     }
773     ret = xmlSchemaGetPredefinedType(name, namespace);
774 #ifdef DEBUG
775     if (ret == NULL) {
776         if (namespace == NULL)
777             fprintf(stderr, "Unable to lookup type %s", name);
778         else
779             fprintf(stderr, "Unable to lookup type %s:%s", name, namespace);
780     }
781 #endif
782     return(ret);
783 }
784
785 /************************************************************************
786  *                                                                      *
787  *                      Parsing functions                               *
788  *                                                                      *
789  ************************************************************************/
790
791 #define IS_BLANK_NODE(n)                                                \
792     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
793
794 /**
795  * xmlSchemaIsBlank:
796  * @str:  a string
797  *
798  * Check if a string is ignorable
799  *
800  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
801  */
802 static int
803 xmlSchemaIsBlank(xmlChar *str) {
804     if (str == NULL)
805         return(1);
806     while (*str != 0) {
807         if (!(IS_BLANK(*str))) return(0);
808         str++;
809     }
810     return(1);
811 }
812
813 /**
814  * xmlSchemaAddNotation:
815  * @ctxt:  a schema validation context
816  * @schema:  the schema being built
817  * @name:  the item name
818  *
819  * Add an XML schema Attrribute declaration
820  * *WARNING* this interface is highly subject to change
821  *
822  * Returns the new struture or NULL in case of error
823  */
824 static xmlSchemaNotationPtr
825 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
826                       const xmlChar * name)
827 {
828     xmlSchemaNotationPtr ret = NULL;
829     int val;
830
831     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
832         return (NULL);
833
834     if (schema->notaDecl == NULL)
835         schema->notaDecl = xmlHashCreate(10);
836     if (schema->notaDecl == NULL)
837         return (NULL);
838
839     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
840     if (ret == NULL) {
841         ctxt->nberrors++;
842         if ((ctxt != NULL) && (ctxt->error != NULL))
843             ctxt->error(ctxt->userData, "Out of memory\n");
844         return (NULL);
845     }
846     memset(ret, 0, sizeof(xmlSchemaNotation));
847     ret->name = xmlStrdup(name);
848     val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
849                            ret);
850     if (val != 0) {
851         ctxt->nberrors++;
852         if ((ctxt != NULL) && (ctxt->error != NULL))
853             ctxt->error(ctxt->userData, "Notation %s already defined\n",
854                         name);
855         xmlFree((char *) ret->name);
856         xmlFree(ret);
857         return (NULL);
858     }
859     return (ret);
860 }
861
862
863 /**
864  * xmlSchemaAddAttribute:
865  * @ctxt:  a schema validation context
866  * @schema:  the schema being built
867  * @name:  the item name
868  * @container:  the container's name
869  *
870  * Add an XML schema Attrribute declaration
871  * *WARNING* this interface is highly subject to change
872  *
873  * Returns the new struture or NULL in case of error
874  */
875 static xmlSchemaAttributePtr
876 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
877                       const xmlChar * name)
878 {
879     xmlSchemaAttributePtr ret = NULL;
880     int val;
881
882     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
883         return (NULL);
884
885     if (schema->attrDecl == NULL)
886         schema->attrDecl = xmlHashCreate(10);
887     if (schema->attrDecl == NULL)
888         return (NULL);
889
890     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
891     if (ret == NULL) {
892         ctxt->nberrors++;
893         if ((ctxt != NULL) && (ctxt->error != NULL))
894             ctxt->error(ctxt->userData, "Out of memory\n");
895         return (NULL);
896     }
897     memset(ret, 0, sizeof(xmlSchemaAttribute));
898     ret->name = xmlStrdup(name);
899     val = xmlHashAddEntry3(schema->attrDecl, name,
900                            schema->targetNamespace, ctxt->container, ret);
901     if (val != 0) {
902         ctxt->nberrors++;
903         if ((ctxt != NULL) && (ctxt->error != NULL))
904             ctxt->error(ctxt->userData, "Attribute %s already defined\n",
905                         name);
906         xmlFree((char *) ret->name);
907         xmlFree(ret);
908         return (NULL);
909     }
910     return (ret);
911 }
912
913 /**
914  * xmlSchemaAddAttributeGroup:
915  * @ctxt:  a schema validation context
916  * @schema:  the schema being built
917  * @name:  the item name
918  *
919  * Add an XML schema Attrribute Group declaration
920  *
921  * Returns the new struture or NULL in case of error
922  */
923 static xmlSchemaAttributeGroupPtr
924 xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
925                            const xmlChar * name)
926 {
927     xmlSchemaAttributeGroupPtr ret = NULL;
928     int val;
929
930     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
931         return (NULL);
932
933     if (schema->attrgrpDecl == NULL)
934         schema->attrgrpDecl = xmlHashCreate(10);
935     if (schema->attrgrpDecl == NULL)
936         return (NULL);
937
938     ret = (xmlSchemaAttributeGroupPtr) xmlMalloc(sizeof(xmlSchemaAttributeGroup));
939     if (ret == NULL) {
940         ctxt->nberrors++;
941         if ((ctxt != NULL) && (ctxt->error != NULL))
942             ctxt->error(ctxt->userData, "Out of memory\n");
943         return (NULL);
944     }
945     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
946     ret->name = xmlStrdup(name);
947     val = xmlHashAddEntry3(schema->attrgrpDecl, name,
948                            schema->targetNamespace, ctxt->container, ret);
949     if (val != 0) {
950         ctxt->nberrors++;
951         if ((ctxt != NULL) && (ctxt->error != NULL))
952             ctxt->error(ctxt->userData, "Attribute group %s already defined\n",
953                         name);
954         xmlFree((char *) ret->name);
955         xmlFree(ret);
956         return (NULL);
957     }
958     return (ret);
959 }
960
961 /**
962  * xmlSchemaAddElement:
963  * @ctxt:  a schema validation context
964  * @schema:  the schema being built
965  * @name:  the type name
966  * @namespace:  the type namespace
967  *
968  * Add an XML schema Element declaration
969  * *WARNING* this interface is highly subject to change
970  *
971  * Returns the new struture or NULL in case of error
972  */
973 static xmlSchemaElementPtr
974 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
975                     const xmlChar * name, const xmlChar * namespace)
976 {
977     xmlSchemaElementPtr ret = NULL;
978     int val;
979
980     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
981         return (NULL);
982
983     if (schema->elemDecl == NULL)
984         schema->elemDecl = xmlHashCreate(10);
985     if (schema->elemDecl == NULL)
986         return (NULL);
987
988     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
989     if (ret == NULL) {
990         ctxt->nberrors++;
991         if ((ctxt != NULL) && (ctxt->error != NULL))
992             ctxt->error(ctxt->userData, "Out of memory\n");
993         return (NULL);
994     }
995     memset(ret, 0, sizeof(xmlSchemaElement));
996     ret->name = xmlStrdup(name);
997     val = xmlHashAddEntry3(schema->elemDecl, name,
998                            namespace, ctxt->container, ret);
999     if (val != 0) {
1000         char buf[100];
1001
1002         snprintf(buf, 99, "privatieelem%d", ctxt->counter++ + 1);
1003         val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1004                                namespace, ret);
1005         if (val != 0) {
1006             ctxt->nberrors++;
1007             if ((ctxt != NULL) && (ctxt->error != NULL))
1008                 ctxt->error(ctxt->userData, "Element %s already defined\n",
1009                             name);
1010             xmlFree((char *) ret->name);
1011             xmlFree(ret);
1012             return (NULL);
1013         }
1014     }
1015     return (ret);
1016 }
1017
1018 /**
1019  * xmlSchemaAddType:
1020  * @ctxt:  a schema validation context
1021  * @schema:  the schema being built
1022  * @name:  the item name
1023  *
1024  * Add an XML schema Simple Type definition
1025  * *WARNING* this interface is highly subject to change
1026  *
1027  * Returns the new struture or NULL in case of error
1028  */
1029 static xmlSchemaTypePtr
1030 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1031                  const xmlChar * name)
1032 {
1033     xmlSchemaTypePtr ret = NULL;
1034     int val;
1035
1036     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1037         return (NULL);
1038
1039     if (schema->typeDecl == NULL)
1040         schema->typeDecl = xmlHashCreate(10);
1041     if (schema->typeDecl == NULL)
1042         return (NULL);
1043
1044     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1045     if (ret == NULL) {
1046         ctxt->nberrors++;
1047         if ((ctxt != NULL) && (ctxt->error != NULL))
1048             ctxt->error(ctxt->userData, "Out of memory\n");
1049         return (NULL);
1050     }
1051     memset(ret, 0, sizeof(xmlSchemaType));
1052     ret->name = xmlStrdup(name);
1053     val = xmlHashAddEntry2(schema->typeDecl, name, schema->targetNamespace,
1054                            ret);
1055     if (val != 0) {
1056         ctxt->nberrors++;
1057         if ((ctxt != NULL) && (ctxt->error != NULL))
1058             ctxt->error(ctxt->userData, "Type %s already defined\n", name);
1059         xmlFree((char *) ret->name);
1060         xmlFree(ret);
1061         return (NULL);
1062     }
1063     ret->minOccurs = 1;
1064     ret->maxOccurs = 1;
1065
1066     return (ret);
1067 }
1068
1069 /**
1070  * xmlSchemaAddGroup:
1071  * @ctxt:  a schema validation context
1072  * @schema:  the schema being built
1073  * @name:  the group name
1074  *
1075  * Add an XML schema Group definition
1076  *
1077  * Returns the new struture or NULL in case of error
1078  */
1079 static xmlSchemaTypePtr
1080 xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1081                  const xmlChar * name)
1082 {
1083     xmlSchemaTypePtr ret = NULL;
1084     int val;
1085
1086     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1087         return (NULL);
1088
1089     if (schema->groupDecl == NULL)
1090         schema->groupDecl = xmlHashCreate(10);
1091     if (schema->groupDecl == NULL)
1092         return (NULL);
1093
1094     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1095     if (ret == NULL) {
1096         ctxt->nberrors++;
1097         if ((ctxt != NULL) && (ctxt->error != NULL))
1098             ctxt->error(ctxt->userData, "Out of memory\n");
1099         return (NULL);
1100     }
1101     memset(ret, 0, sizeof(xmlSchemaType));
1102     ret->name = xmlStrdup(name);
1103     val = xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1104                            ret);
1105     if (val != 0) {
1106         ctxt->nberrors++;
1107         if ((ctxt != NULL) && (ctxt->error != NULL))
1108             ctxt->error(ctxt->userData, "Group %s already defined\n", name);
1109         xmlFree((char *) ret->name);
1110         xmlFree(ret);
1111         return (NULL);
1112     }
1113     ret->minOccurs = 1;
1114     ret->maxOccurs = 1;
1115
1116     return (ret);
1117 }
1118
1119 /************************************************************************
1120  *                                                                      *
1121  *              Utilities for parsing                                   *
1122  *                                                                      *
1123  ************************************************************************/
1124
1125 /**
1126  * xmlGetQNameProp:
1127  * @ctxt:  a schema validation context
1128  * @node:  a subtree containing XML Schema informations
1129  * @name:  the attribute name
1130  * @namespace:  the result namespace if any
1131  *
1132  * Extract a QName Attribute value
1133  *
1134  * Returns the NCName or NULL if not found, and also update @namespace
1135  *    with the namespace URI
1136  */
1137 static xmlChar *
1138 xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1139                 const char *name,
1140                 xmlChar **namespace) {
1141     xmlChar *val, *ret, *prefix;
1142     xmlNsPtr ns;
1143
1144
1145     if (namespace != NULL)
1146         *namespace = NULL;
1147     val = xmlGetProp(node, (const xmlChar *) name);
1148     if (val == NULL)
1149         return(NULL);
1150
1151     ret = xmlSplitQName2(val, &prefix);
1152     if (ret == NULL)
1153         return(val);
1154     xmlFree(val);
1155
1156     ns = xmlSearchNs(node->doc, node, prefix);
1157     if (ns == NULL) {
1158         ctxt->nberrors++;
1159         xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1160         if ((ctxt != NULL) && (ctxt->error != NULL))
1161             ctxt->error(ctxt->userData,
1162                     "Attribute %s: the QName prefix %s is undefined\n",
1163                         name, prefix);
1164     } else {
1165         *namespace = xmlStrdup(ns->href);
1166     }
1167     xmlFree(prefix);
1168     return(ret);
1169 }
1170
1171 /**
1172  * xmlGetMaxOccurs:
1173  * @ctxt:  a schema validation context
1174  * @node:  a subtree containing XML Schema informations
1175  *
1176  * Get the maxOccurs property
1177  *
1178  * Returns the default if not found, or the value
1179  */
1180 static int
1181 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) {
1182     xmlChar *val, *cur;
1183     int ret = 0;
1184
1185     val = xmlGetProp(node, (const xmlChar *) "maxOccurs");
1186     if (val == NULL)
1187         return(1);
1188
1189     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
1190         xmlFree(val);
1191         return(UNBOUNDED); /* encoding it with -1 might be another option */
1192     }
1193
1194     cur = val;
1195     while (IS_BLANK(*cur)) cur++;
1196     while ((*cur >= '0') && (*cur <= '9')) {
1197         ret = ret * 10 + (*cur - '0');
1198         cur++;
1199     }
1200     while (IS_BLANK(*cur)) cur++;
1201     if (*cur != 0) {
1202         ctxt->nberrors++;
1203         xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1204         if ((ctxt != NULL) && (ctxt->error != NULL))
1205             ctxt->error(ctxt->userData, "invalid value for minOccurs: %s\n",
1206                         val);
1207         xmlFree(val);
1208         return(1);
1209     }
1210     xmlFree(val);
1211     return(ret);
1212 }
1213
1214 /**
1215  * xmlGetMinOccurs:
1216  * @ctxt:  a schema validation context
1217  * @node:  a subtree containing XML Schema informations
1218  *
1219  * Get the minOccurs property
1220  *
1221  * Returns the default if not found, or the value
1222  */
1223 static int
1224 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) {
1225     xmlChar *val, *cur;
1226     int ret = 0;
1227
1228     val = xmlGetProp(node, (const xmlChar *) "minOccurs");
1229     if (val == NULL)
1230         return(1);
1231
1232     cur = val;
1233     while (IS_BLANK(*cur)) cur++;
1234     while ((*cur >= '0') && (*cur <= '9')) {
1235         ret = ret * 10 + (*cur - '0');
1236         cur++;
1237     }
1238     while (IS_BLANK(*cur)) cur++;
1239     if (*cur != 0) {
1240         ctxt->nberrors++;
1241         xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1242         if ((ctxt != NULL) && (ctxt->error != NULL))
1243             ctxt->error(ctxt->userData, "invalid value for minOccurs: %s\n",
1244                         val);
1245         xmlFree(val);
1246         return(1);
1247     }
1248     xmlFree(val);
1249     return(ret);
1250 }
1251
1252 /**
1253  * xmlGetBooleanProp:
1254  * @ctxt:  a schema validation context
1255  * @node:  a subtree containing XML Schema informations
1256  * @name:  the attribute name
1257  * @def:  the default value
1258  *
1259  * Get is a bolean property is set
1260  *
1261  * Returns the default if not found, 0 if found to be false,
1262  *         1 if found to be true
1263  */
1264 static int
1265 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1266                   const char *name, int def) {
1267     xmlChar *val;
1268
1269     val = xmlGetProp(node, (const xmlChar *) name);
1270     if (val == NULL)
1271         return(def);
1272
1273     if (xmlStrEqual(val, BAD_CAST"true"))
1274         def = 1;
1275     else if (xmlStrEqual(val, BAD_CAST"false"))
1276         def = 0;
1277     else {
1278         ctxt->nberrors++;
1279         xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1280         if ((ctxt != NULL) && (ctxt->error != NULL))
1281             ctxt->error(ctxt->userData,
1282                     "Attribute %s: the value %s is not boolean\n",
1283                         name, val);
1284     }
1285     xmlFree(val);
1286     return(def);
1287 }
1288
1289 /************************************************************************
1290  *                                                                      *
1291  *              Shema extraction from an Infoset                        *
1292  *                                                                      *
1293  ************************************************************************/
1294 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1295                                                  ctxt, xmlSchemaPtr schema,
1296                                                  xmlNodePtr node);
1297 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,
1298                                                   xmlSchemaPtr schema,
1299                                                   xmlNodePtr node);
1300 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,
1301                                                   xmlSchemaPtr schema,
1302                                                   xmlNodePtr node,
1303                                                   int simple);
1304 static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1305                                                xmlSchemaPtr schema,
1306                                                xmlNodePtr node);
1307 static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1308                                           xmlSchemaPtr schema,
1309                                           xmlNodePtr node);
1310 static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1311                                                      ctxt,
1312                                                      xmlSchemaPtr schema,
1313                                                      xmlNodePtr node);
1314 static xmlSchemaAttributeGroupPtr
1315 xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1316                              xmlSchemaPtr schema, xmlNodePtr node);
1317 static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1318                                              xmlSchemaPtr schema,
1319                                              xmlNodePtr node);
1320 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1321                                            xmlSchemaPtr schema,
1322                                            xmlNodePtr node);
1323 static xmlSchemaAttributePtr
1324 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1325                            xmlNodePtr node);
1326
1327 /**
1328  * xmlSchemaParseAttrDecls:
1329  * @ctxt:  a schema validation context
1330  * @schema:  the schema being built
1331  * @node:  a subtree containing XML Schema informations
1332  * @type:  the hosting type
1333  *
1334  * parse a XML schema attrDecls declaration corresponding to
1335  * <!ENTITY % attrDecls  
1336  *       '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1337  */
1338 static xmlNodePtr
1339 xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1340                         xmlNodePtr child, xmlSchemaTypePtr type)
1341 {
1342     xmlSchemaAttributePtr lastattr, attr;
1343
1344     lastattr = NULL;
1345     while ((IS_SCHEMA(child, "attribute")) ||
1346            (IS_SCHEMA(child, "attributeGroup"))) {
1347         attr = NULL;
1348         if (IS_SCHEMA(child, "attribute")) {
1349             attr = xmlSchemaParseAttribute(ctxt, schema, child);
1350         } else if (IS_SCHEMA(child, "attributeGroup")) {
1351             attr = (xmlSchemaAttributePtr)
1352                 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1353         }
1354         if (attr != NULL) {
1355             if (lastattr == NULL) {
1356                 type->attributes = attr;
1357                 lastattr = attr
1358                           ;
1359             } else {
1360                 lastattr->next = attr;
1361                 lastattr = attr;
1362             }
1363         }
1364         child = child->next;
1365     }
1366     if (IS_SCHEMA(child, "anyAttribute")) {
1367         attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1368         if (attr != NULL) {
1369             if (lastattr == NULL) {
1370                 type->attributes = attr;
1371                 lastattr = attr
1372                           ;
1373             } else {
1374                 lastattr->next = attr;
1375                 lastattr = attr;
1376             }
1377         }
1378         child = child->next;
1379     }
1380     return(child);
1381 }
1382
1383 /**
1384  * xmlSchemaParseAnnotation:
1385  * @ctxt:  a schema validation context
1386  * @schema:  the schema being built
1387  * @node:  a subtree containing XML Schema informations
1388  *
1389  * parse a XML schema Attrribute declaration
1390  * *WARNING* this interface is highly subject to change
1391  *
1392  * Returns -1 in case of error, 0 if the declaration is inproper and
1393  *         1 in case of success.
1394  */
1395 static xmlSchemaAnnotPtr
1396 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1397                          xmlNodePtr node)
1398 {
1399     xmlSchemaAnnotPtr ret;
1400
1401     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1402         return (NULL);
1403     ret = xmlSchemaNewAnnot(ctxt, node);
1404
1405     return (ret);
1406 }
1407
1408 /**
1409  * xmlSchemaParseFacet:
1410  * @ctxt:  a schema validation context
1411  * @schema:  the schema being built
1412  * @node:  a subtree containing XML Schema informations
1413  *
1414  * parse a XML schema Facet declaration
1415  * *WARNING* this interface is highly subject to change
1416  *
1417  * Returns the new type structure or NULL in case of error
1418  */
1419 static xmlSchemaFacetPtr
1420 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1421                   xmlNodePtr node)
1422 {
1423     xmlSchemaFacetPtr facet;
1424     xmlNodePtr child = NULL;
1425     xmlChar *value;
1426
1427     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1428         return (NULL);
1429
1430     facet = xmlSchemaNewFacet();
1431     if (facet == NULL)
1432         return (NULL);
1433     facet->node = node;
1434     value = xmlGetProp(node, (const xmlChar *) "value");
1435     if (value == NULL) {
1436         ctxt->nberrors++;
1437         xmlSchemaErrorContext(ctxt, schema, node, child);
1438         if ((ctxt != NULL) && (ctxt->error != NULL))
1439             ctxt->error(ctxt->userData, "Facet %s has no value\n", node->name);
1440         xmlSchemaFreeFacet(facet);
1441         return (NULL);
1442     }
1443     if (IS_SCHEMA(node, "minInclusive"))  {
1444         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
1445     } else if (IS_SCHEMA(node, "minExclusive"))  {
1446         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
1447     } else if (IS_SCHEMA(node, "maxInclusive"))  {
1448         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
1449     } else if (IS_SCHEMA(node, "maxExclusive"))  {
1450         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
1451     } else if (IS_SCHEMA(node, "totalDigits"))  {
1452         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
1453     } else if (IS_SCHEMA(node, "fractionDigits"))  {
1454         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
1455     } else if (IS_SCHEMA(node, "pattern"))  {
1456         facet->type = XML_SCHEMA_FACET_PATTERN;
1457     } else if (IS_SCHEMA(node, "enumeration"))  {
1458         facet->type = XML_SCHEMA_FACET_ENUMERATION;
1459     } else if (IS_SCHEMA(node, "whiteSpace"))  {
1460         facet->type = XML_SCHEMA_FACET_WHITESPACE;
1461     } else if (IS_SCHEMA(node, "length"))  {
1462         facet->type = XML_SCHEMA_FACET_LENGTH;
1463     } else if (IS_SCHEMA(node, "maxLength"))  {
1464         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1465     } else if (IS_SCHEMA(node, "minLength")) {
1466         facet->type = XML_SCHEMA_FACET_MINLENGTH;
1467     } else {
1468         ctxt->nberrors++;
1469         xmlSchemaErrorContext(ctxt, schema, node, child);
1470         if ((ctxt != NULL) && (ctxt->error != NULL))
1471             ctxt->error(ctxt->userData, "Unknown facet type %s\n", node->name);
1472         xmlSchemaFreeFacet(facet);
1473         return(NULL);
1474     }
1475     facet->id = xmlGetProp(node, (const xmlChar *) "id");
1476     facet->value = value;
1477     child = node->children;
1478
1479     if (IS_SCHEMA(child, "annotation")) {
1480         facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1481         child = child->next;
1482     }
1483     if (child != NULL) {
1484         ctxt->nberrors++;
1485         xmlSchemaErrorContext(ctxt, schema, node, child);
1486         if ((ctxt != NULL) && (ctxt->error != NULL))
1487             ctxt->error(ctxt->userData,
1488                         "Facet %s has unexpected child content\n",
1489                         node->name);
1490     }
1491     return (facet);
1492 }
1493
1494 /**
1495  * xmlSchemaParseAny:
1496  * @ctxt:  a schema validation context
1497  * @schema:  the schema being built
1498  * @node:  a subtree containing XML Schema informations
1499  *
1500  * parse a XML schema Any declaration
1501  * *WARNING* this interface is highly subject to change
1502  *
1503  * Returns the new type structure or NULL in case of error
1504  */
1505 static xmlSchemaTypePtr
1506 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1507                   xmlNodePtr node)
1508 {
1509     xmlSchemaTypePtr type;
1510     xmlNodePtr child = NULL;
1511     xmlChar name[30];
1512
1513     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1514         return (NULL);
1515     snprintf((char *)name, 30, "any %d", ctxt->counter++ + 1);
1516     type = xmlSchemaAddType(ctxt, schema, name);
1517     if (type == NULL)
1518         return (NULL);
1519     type->node = node;
1520     type->type = XML_SCHEMA_TYPE_ANY;
1521     child = node->children;
1522     type->minOccurs = xmlGetMinOccurs(ctxt, node);
1523     type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1524
1525     if (IS_SCHEMA(child, "annotation")) {
1526         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1527         child = child->next;
1528     }
1529     if (child != NULL) {
1530         ctxt->nberrors++;
1531         xmlSchemaErrorContext(ctxt, schema, node, child);
1532         if ((ctxt != NULL) && (ctxt->error != NULL))
1533             ctxt->error(ctxt->userData,
1534                         "Sequence %s has unexpected content\n",
1535                         type->name);
1536     }
1537
1538     return (type);
1539 }
1540
1541 /**
1542  * xmlSchemaParseNotation:
1543  * @ctxt:  a schema validation context
1544  * @schema:  the schema being built
1545  * @node:  a subtree containing XML Schema informations
1546  *
1547  * parse a XML schema Notation declaration
1548  *
1549  * Returns the new structure or NULL in case of error
1550  */
1551 static xmlSchemaNotationPtr
1552 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1553                         xmlNodePtr node)
1554 {
1555     xmlChar *name;
1556     xmlSchemaNotationPtr ret;
1557     xmlNodePtr child = NULL;
1558
1559     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1560         return (NULL);
1561     name = xmlGetProp(node, (const xmlChar *) "name");
1562     if (name == NULL) {
1563         ctxt->nberrors++;
1564         xmlSchemaErrorContext(ctxt, schema, node, child);
1565         if ((ctxt != NULL) && (ctxt->error != NULL))
1566             ctxt->error(ctxt->userData, "Notation has no name\n");
1567         return (NULL);
1568     }
1569     ret = xmlSchemaAddNotation(ctxt, schema, name);
1570     if (ret == NULL) {
1571         xmlFree(name);
1572         return (NULL);
1573     }
1574     child = node->children;
1575     if (IS_SCHEMA(child, "annotation")) {
1576         ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1577         child = child->next;
1578     }
1579     if (child != NULL) {
1580         ctxt->nberrors++;
1581         xmlSchemaErrorContext(ctxt, schema, node, child);
1582         if ((ctxt != NULL) && (ctxt->error != NULL))
1583             ctxt->error(ctxt->userData,
1584                         "notation %s has unexpected content\n",
1585                         name);
1586     }
1587
1588     return (ret);
1589 }
1590
1591 /**
1592  * xmlSchemaParseAnyAttribute:
1593  * @ctxt:  a schema validation context
1594  * @schema:  the schema being built
1595  * @node:  a subtree containing XML Schema informations
1596  *
1597  * parse a XML schema AnyAttrribute declaration
1598  * *WARNING* this interface is highly subject to change
1599  *
1600  * Returns an attribute def structure or NULL
1601  */
1602 static xmlSchemaAttributePtr
1603 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1604                         xmlNodePtr node)
1605 {
1606     xmlChar *processContents;
1607     xmlSchemaAttributePtr ret;
1608     xmlNodePtr child = NULL;
1609     char name[100];
1610
1611     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1612         return (NULL);
1613
1614     snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
1615     ret = xmlSchemaAddAttribute(ctxt, schema, (xmlChar *)name);
1616     if (ret == NULL) {
1617         return (NULL);
1618     }
1619     ret->id = xmlGetProp(node, (const xmlChar *) "id");
1620     processContents = xmlGetProp(node, (const xmlChar *) "processContents");
1621     if ((processContents == NULL) ||
1622         (xmlStrEqual(processContents, (const xmlChar *)"strict"))) {
1623         ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1624     } else if (xmlStrEqual(processContents, (const xmlChar *)"skip")) {
1625         ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1626     } else if (xmlStrEqual(processContents, (const xmlChar *)"lax")) {
1627         ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
1628     } else {
1629         ctxt->nberrors++;
1630         xmlSchemaErrorContext(ctxt, schema, node, child);
1631         if ((ctxt != NULL) && (ctxt->error != NULL))
1632             ctxt->error(ctxt->userData,
1633             "anyAttribute has unexpected content for processContents: %s\n",
1634                         processContents);
1635         ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1636     }
1637     if (processContents != NULL)
1638         xmlFree(processContents);
1639
1640     child = node->children;
1641     if (IS_SCHEMA(child, "annotation")) {
1642         ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1643         child = child->next;
1644     }
1645     if (child != NULL) {
1646         ctxt->nberrors++;
1647         xmlSchemaErrorContext(ctxt, schema, node, child);
1648         if ((ctxt != NULL) && (ctxt->error != NULL))
1649             ctxt->error(ctxt->userData,
1650                         "anyAttribute %s has unexpected content\n",
1651                         name);
1652     }
1653
1654     return (ret);
1655 }
1656
1657
1658 /**
1659  * xmlSchemaParseAttribute:
1660  * @ctxt:  a schema validation context
1661  * @schema:  the schema being built
1662  * @node:  a subtree containing XML Schema informations
1663  *
1664  * parse a XML schema Attrribute declaration
1665  * *WARNING* this interface is highly subject to change
1666  *
1667  * Returns -1 in case of error, 0 if the declaration is inproper and
1668  *         1 in case of success.
1669  */
1670 static xmlSchemaAttributePtr
1671 xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1672                         xmlNodePtr node)
1673 {
1674     xmlChar *name, *refNs = NULL, *ref = NULL;
1675     xmlSchemaAttributePtr ret;
1676     xmlNodePtr child = NULL;
1677
1678     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1679         return (NULL);
1680     name = xmlGetProp(node, (const xmlChar *) "name");
1681     if (name == NULL) {
1682         char buf[100];
1683
1684         ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1685         if (ref == NULL) {
1686             ctxt->nberrors++;
1687             xmlSchemaErrorContext(ctxt, schema, node, child);
1688             if ((ctxt != NULL) && (ctxt->error != NULL))
1689                 ctxt->error(ctxt->userData, "Attribute has no name nor ref\n");
1690             return (NULL);
1691         }
1692         snprintf(buf, 99, "anonattr%d", ctxt->counter++ + 1);
1693         name = xmlStrdup((xmlChar *) buf);
1694     }
1695     ret = xmlSchemaAddAttribute(ctxt, schema, name);
1696     if (ret == NULL) {
1697         xmlFree(name);
1698         if (ref != NULL)
1699             xmlFree(ref);
1700         return (NULL);
1701     }
1702     xmlFree(name);
1703     ret->ref = ref;
1704     ret->refNs = refNs;
1705     ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
1706     ret->node = node;
1707     child = node->children;
1708     if (IS_SCHEMA(child, "annotation")) {
1709         ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1710         child = child->next;
1711     }
1712     if (IS_SCHEMA(child, "simpleType")) {
1713         ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1714         child = child->next;
1715     }
1716     if (child != NULL) {
1717         ctxt->nberrors++;
1718         xmlSchemaErrorContext(ctxt, schema, node, child);
1719         if ((ctxt != NULL) && (ctxt->error != NULL))
1720             ctxt->error(ctxt->userData,
1721                         "attribute %s has unexpected content\n",
1722                         name);
1723     }
1724
1725     return (ret);
1726 }
1727
1728 /**
1729  * xmlSchemaParseAttributeGroup:
1730  * @ctxt:  a schema validation context
1731  * @schema:  the schema being built
1732  * @node:  a subtree containing XML Schema informations
1733  *
1734  * parse a XML schema Attribute Group declaration
1735  * *WARNING* this interface is highly subject to change
1736  *
1737  * Returns the attribute group or NULL in case of error.
1738  */
1739 static xmlSchemaAttributeGroupPtr
1740 xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1741                              xmlNodePtr node)
1742 {
1743     xmlChar *name, *refNs = NULL, *ref = NULL;
1744     xmlSchemaAttributeGroupPtr ret;
1745     xmlSchemaAttributePtr last = NULL, attr;
1746     xmlNodePtr child = NULL;
1747     xmlChar *oldcontainer;
1748
1749     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1750         return (NULL);
1751     oldcontainer = ctxt->container;
1752     name = xmlGetProp(node, (const xmlChar *) "name");
1753     if (name == NULL) {
1754         char buf[100];
1755
1756         ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1757         if (ref == NULL) {
1758             ctxt->nberrors++;
1759             xmlSchemaErrorContext(ctxt, schema, node, child);
1760             if ((ctxt != NULL) && (ctxt->error != NULL))
1761                 ctxt->error(ctxt->userData,
1762                         "AttributeGroup has no name nor ref\n");
1763             return (NULL);
1764         }
1765         snprintf(buf, 99, "anonattrgroup%d", ctxt->counter++ + 1);
1766         name = xmlStrdup((xmlChar *) buf);
1767         if (name == NULL) {
1768             ctxt->nberrors++;
1769             if ((ctxt != NULL) && (ctxt->error != NULL))
1770                 ctxt->error(ctxt->userData,
1771                         "out of memory\n");
1772             return (NULL);
1773         }
1774     }
1775     ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
1776     if (ret == NULL) {
1777         xmlFree(name);
1778         if (ref != NULL)
1779             xmlFree(ref);
1780         return (NULL);
1781     }
1782     ret->ref = ref;
1783     ret->refNs = refNs;
1784     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
1785     ret->node = node;
1786     child = node->children;
1787     ctxt->container = name;
1788     if (IS_SCHEMA(child, "annotation")) {
1789         ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1790         child = child->next;
1791     }
1792     while ((IS_SCHEMA(child, "attribute")) ||
1793            (IS_SCHEMA(child, "attributeGroup"))) {
1794         attr = NULL;
1795         if (IS_SCHEMA(child, "attribute")) {
1796             attr = xmlSchemaParseAttribute(ctxt, schema, child);
1797         } else if (IS_SCHEMA(child, "attributeGroup")) {
1798             attr = (xmlSchemaAttributePtr)
1799                 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1800         }
1801         if (attr != NULL) {
1802             if (last == NULL) {
1803                 ret->attributes = attr;
1804                 last = attr;
1805             } else {
1806                 last->next = attr;
1807                 last = attr;
1808             }
1809         }
1810         child = child->next;
1811     }
1812     if (IS_SCHEMA(child, "anyAttribute")) {
1813         TODO
1814         child = child->next;
1815     }
1816     if (child != NULL) {
1817         ctxt->nberrors++;
1818         xmlSchemaErrorContext(ctxt, schema, node, child);
1819         if ((ctxt != NULL) && (ctxt->error != NULL))
1820             ctxt->error(ctxt->userData,
1821                         "attribute group %s has unexpected content\n",
1822                         name);
1823     }
1824
1825     ctxt->container = oldcontainer;
1826     xmlFree(name);
1827     return (ret);
1828 }
1829
1830 /**
1831  * xmlSchemaParseElement:
1832  * @ctxt:  a schema validation context
1833  * @schema:  the schema being built
1834  * @node:  a subtree containing XML Schema informations
1835  *
1836  * parse a XML schema Element declaration
1837  * *WARNING* this interface is highly subject to change
1838  *
1839  * Returns -1 in case of error, 0 if the declaration is inproper and
1840  *         1 in case of success.
1841  */
1842 static xmlSchemaElementPtr
1843 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1844                       xmlNodePtr node, int toplevel)
1845 {
1846     xmlChar *name, *refNs = NULL, *ref = NULL, *namespace, *fixed;
1847     xmlSchemaElementPtr ret;
1848     xmlNodePtr child = NULL;
1849     xmlChar *oldcontainer;
1850
1851     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1852         return (NULL);
1853     oldcontainer = ctxt->container;
1854     name = xmlGetProp(node, (const xmlChar *) "name");
1855     if (name == NULL) {
1856         char buf[100];
1857
1858         ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1859         if (ref == NULL) {
1860             ctxt->nberrors++;
1861             xmlSchemaErrorContext(ctxt, schema, node, child);
1862             if ((ctxt != NULL) && (ctxt->error != NULL))
1863                 ctxt->error(ctxt->userData, "Element has no name nor ref\n");
1864             return (NULL);
1865         }
1866         snprintf(buf, 99, "anonelem%d", ctxt->counter++ + 1);
1867         name = xmlStrdup((xmlChar *) buf);
1868     }
1869     namespace = xmlGetProp(node, (const xmlChar *) "targetNamespace");
1870     if (namespace == NULL)
1871         ret =
1872             xmlSchemaAddElement(ctxt, schema, name,
1873                                 schema->targetNamespace);
1874     else
1875         ret = xmlSchemaAddElement(ctxt, schema, name, namespace);
1876     ret->node = node;
1877     if (namespace != NULL)
1878         xmlFree(namespace);
1879     if (ret == NULL) {
1880         xmlFree(name);
1881         if (ref != NULL)
1882             xmlFree(ref);
1883         return (NULL);
1884     }
1885     ret->type = XML_SCHEMA_TYPE_ELEMENT;
1886     ret->ref = ref;
1887     ret->refNs = refNs;
1888     if (ref != NULL)
1889         ret->flags |= XML_SCHEMAS_ELEM_REF;
1890     if (toplevel)
1891         ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
1892     if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
1893         ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1894     if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
1895         ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1896     ctxt->container = name;
1897
1898     ret->id = xmlGetProp(node, BAD_CAST "id");
1899     ret->namedType = xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
1900     ret->substGroup = xmlGetQNameProp(ctxt, node, "substitutionGroup",
1901                                       &(ret->substGroupNs));
1902     fixed = xmlGetProp(node, BAD_CAST "fixed");
1903     ret->minOccurs = xmlGetMinOccurs(ctxt, node);
1904     ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1905     
1906     ret->value = xmlGetProp(node, BAD_CAST "default");
1907     if ((ret->value != NULL) && (fixed != NULL)) {
1908         ctxt->nberrors++;
1909         xmlSchemaErrorContext(ctxt, schema, node, child);
1910         ctxt->error(ctxt->userData,
1911                     "Element %s has both default and fixed\n",
1912                     ret->name);
1913         xmlFree(fixed);
1914     } else if (fixed != NULL) {
1915         ret->flags |= XML_SCHEMAS_ELEM_FIXED;
1916         ret->value = fixed;
1917     }
1918
1919     child = node->children;
1920     if (IS_SCHEMA(child, "annotation")) {
1921         ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1922         child = child->next;
1923     }
1924     if (IS_SCHEMA(child, "complexType")) {
1925         ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
1926         child = child->next;
1927     } else if (IS_SCHEMA(child, "simpleType")) {
1928         ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1929         child = child->next;
1930     }
1931     while ((IS_SCHEMA(child, "unique")) ||
1932            (IS_SCHEMA(child, "key")) ||
1933            (IS_SCHEMA(child, "keyref"))) {
1934         TODO
1935         child = child->next;
1936     }
1937     if (child != NULL) {
1938         ctxt->nberrors++;
1939         xmlSchemaErrorContext(ctxt, schema, node, child);
1940         if ((ctxt != NULL) && (ctxt->error != NULL))
1941             ctxt->error(ctxt->userData,
1942                         "element %s has unexpected content\n",
1943                         name);
1944     }
1945
1946     ctxt->container = oldcontainer;
1947     xmlFree(name);
1948     return (ret);
1949 }
1950
1951 /**
1952  * xmlSchemaParseUnion:
1953  * @ctxt:  a schema validation context
1954  * @schema:  the schema being built
1955  * @node:  a subtree containing XML Schema informations
1956  *
1957  * parse a XML schema Union definition
1958  * *WARNING* this interface is highly subject to change
1959  *
1960  * Returns -1 in case of error, 0 if the declaration is inproper and
1961  *         1 in case of success.
1962  */
1963 static xmlSchemaTypePtr
1964 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1965                          xmlNodePtr node)
1966 {
1967     xmlSchemaTypePtr type, subtype, last = NULL;
1968     xmlNodePtr child = NULL;
1969     xmlChar name[30];
1970
1971     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1972         return (NULL);
1973
1974
1975     snprintf((char *)name, 30, "union %d", ctxt->counter++ + 1);
1976     type = xmlSchemaAddType(ctxt, schema, name);
1977     if (type == NULL)
1978         return (NULL);
1979     type->node = node;
1980     type->type = XML_SCHEMA_TYPE_LIST;
1981     type->id = xmlGetProp(node, BAD_CAST "id");
1982     type->ref = xmlGetProp(node, BAD_CAST "memberTypes");
1983
1984     child = node->children;
1985     if (IS_SCHEMA(child, "annotation")) {
1986         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1987         child = child->next;
1988     }
1989     while (IS_SCHEMA(child, "simpleType")) {
1990         subtype = (xmlSchemaTypePtr) 
1991               xmlSchemaParseSimpleType(ctxt, schema, child);
1992         if (subtype != NULL) {
1993             if (last == NULL) {
1994                 type->subtypes = subtype;
1995                 last = subtype;
1996             } else {
1997                 last->next = subtype;
1998                 last = subtype;
1999             }
2000             last->next = NULL;
2001         }
2002         child = child->next;
2003     }
2004     if (child != NULL) {
2005         ctxt->nberrors++;
2006         xmlSchemaErrorContext(ctxt, schema, node, child);
2007         if ((ctxt != NULL) && (ctxt->error != NULL))
2008             ctxt->error(ctxt->userData,
2009                         "Union %s has unexpected content\n",
2010                         type->name);
2011     }
2012     return (type);
2013 }
2014
2015 /**
2016  * xmlSchemaParseList:
2017  * @ctxt:  a schema validation context
2018  * @schema:  the schema being built
2019  * @node:  a subtree containing XML Schema informations
2020  *
2021  * parse a XML schema List definition
2022  * *WARNING* this interface is highly subject to change
2023  *
2024  * Returns -1 in case of error, 0 if the declaration is inproper and
2025  *         1 in case of success.
2026  */
2027 static xmlSchemaTypePtr
2028 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2029                          xmlNodePtr node)
2030 {
2031     xmlSchemaTypePtr type, subtype;
2032     xmlNodePtr child = NULL;
2033     xmlChar name[30];
2034
2035     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2036         return (NULL);
2037
2038     snprintf((char *)name, 30, "list %d", ctxt->counter++ + 1);
2039     type = xmlSchemaAddType(ctxt, schema, name);
2040     if (type == NULL)
2041         return (NULL);
2042     type->node = node;
2043     type->type = XML_SCHEMA_TYPE_LIST;
2044     type->id = xmlGetProp(node, BAD_CAST "id");
2045     type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2046
2047     child = node->children;
2048     if (IS_SCHEMA(child, "annotation")) {
2049         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2050         child = child->next;
2051     }
2052     subtype = NULL;
2053     if (IS_SCHEMA(child, "simpleType")) {
2054         subtype = (xmlSchemaTypePtr) 
2055               xmlSchemaParseSimpleType(ctxt, schema, child);
2056         child = child->next;
2057         type->subtypes = subtype;
2058     }
2059     if (child != NULL) {
2060         ctxt->nberrors++;
2061         xmlSchemaErrorContext(ctxt, schema, node, child);
2062         if ((ctxt != NULL) && (ctxt->error != NULL))
2063             ctxt->error(ctxt->userData,
2064                         "List %s has unexpected content\n",
2065                         type->name);
2066     }
2067     return (type);
2068 }
2069 /**
2070  * xmlSchemaParseSimpleType:
2071  * @ctxt:  a schema validation context
2072  * @schema:  the schema being built
2073  * @node:  a subtree containing XML Schema informations
2074  *
2075  * parse a XML schema Simple Type definition
2076  * *WARNING* this interface is highly subject to change
2077  *
2078  * Returns -1 in case of error, 0 if the declaration is inproper and
2079  *         1 in case of success.
2080  */
2081 static xmlSchemaTypePtr
2082 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2083                          xmlNodePtr node)
2084 {
2085     xmlSchemaTypePtr type, subtype;
2086     xmlNodePtr child = NULL;
2087     xmlChar *name;
2088
2089     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2090         return (NULL);
2091
2092
2093     name = xmlGetProp(node, (const xmlChar *) "name");
2094     if (name == NULL) {
2095         char buf[100];
2096
2097         snprintf(buf, 99, "simpletype%d", ctxt->counter++ + 1);
2098         name = xmlStrdup((xmlChar *) buf);
2099     }
2100     if (name == NULL) {
2101         ctxt->nberrors++;
2102         xmlSchemaErrorContext(ctxt, schema, node, child);
2103         if ((ctxt != NULL) && (ctxt->error != NULL))
2104             ctxt->error(ctxt->userData, "simpleType has no name\n");
2105         return (NULL);
2106     }
2107     type = xmlSchemaAddType(ctxt, schema, name);
2108     xmlFree(name);
2109     if (type == NULL)
2110         return (NULL);
2111     type->node = node;
2112     type->type = XML_SCHEMA_TYPE_SIMPLE;
2113     type->id = xmlGetProp(node, BAD_CAST "id");
2114
2115     child = node->children;
2116     if (IS_SCHEMA(child, "annotation")) {
2117         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2118         child = child->next;
2119     }
2120     subtype = NULL;
2121     if (IS_SCHEMA(child, "restriction")) {
2122         subtype = (xmlSchemaTypePtr) 
2123               xmlSchemaParseRestriction(ctxt, schema, child, 1);
2124         child = child->next;
2125     } else if (IS_SCHEMA(child, "list")) {
2126         subtype = (xmlSchemaTypePtr) 
2127               xmlSchemaParseList(ctxt, schema, child);
2128         child = child->next;
2129     } else if (IS_SCHEMA(child, "union")) {
2130         subtype = (xmlSchemaTypePtr) 
2131               xmlSchemaParseUnion(ctxt, schema, child);
2132         child = child->next;
2133     }
2134     type->subtypes = subtype;
2135     if (child != NULL) {
2136         ctxt->nberrors++;
2137         xmlSchemaErrorContext(ctxt, schema, node, child);
2138         if ((ctxt != NULL) && (ctxt->error != NULL))
2139             ctxt->error(ctxt->userData,
2140                         "SimpleType %s has unexpected content\n",
2141                         type->name);
2142     }
2143
2144     return (type);
2145 }
2146
2147
2148 /**
2149  * xmlSchemaParseGroup:
2150  * @ctxt:  a schema validation context
2151  * @schema:  the schema being built
2152  * @node:  a subtree containing XML Schema informations
2153  *
2154  * parse a XML schema Group definition
2155  * *WARNING* this interface is highly subject to change
2156  *
2157  * Returns -1 in case of error, 0 if the declaration is inproper and
2158  *         1 in case of success.
2159  */
2160 static xmlSchemaTypePtr
2161 xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2162                           xmlNodePtr node)
2163 {
2164     xmlSchemaTypePtr type, subtype;
2165     xmlNodePtr child = NULL;
2166     xmlChar *name, *ref = NULL, *refNs = NULL;
2167
2168     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2169         return (NULL);
2170
2171
2172     name = xmlGetProp(node, (const xmlChar *) "name");
2173     if (name == NULL) {
2174         char buf[100];
2175
2176         ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2177         if (ref == NULL) {
2178             ctxt->nberrors++;
2179             xmlSchemaErrorContext(ctxt, schema, node, child);
2180             if ((ctxt != NULL) && (ctxt->error != NULL))
2181                 ctxt->error(ctxt->userData, "Group has no name nor ref\n");
2182             return (NULL);
2183         }
2184         snprintf(buf, 99, "anongroup%d", ctxt->counter++ + 1);
2185         name = xmlStrdup((xmlChar *) buf);
2186     }
2187     type = xmlSchemaAddGroup(ctxt, schema, name);
2188     if (type == NULL)
2189         return (NULL);
2190     type->node = node;
2191     type->type = XML_SCHEMA_TYPE_GROUP;
2192     type->id = xmlGetProp(node, BAD_CAST "id");
2193     type->ref = ref;
2194     type->refNs = refNs;
2195     type->minOccurs = xmlGetMinOccurs(ctxt, node);
2196     type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2197
2198     child = node->children;
2199     if (IS_SCHEMA(child, "annotation")) {
2200         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2201         child = child->next;
2202     }
2203     subtype = NULL;
2204     if (IS_SCHEMA(child, "all")) {
2205         subtype = (xmlSchemaTypePtr) 
2206               xmlSchemaParseAll(ctxt, schema, child);
2207         child = child->next;
2208     } else if (IS_SCHEMA(child, "choice")) {
2209         subtype = xmlSchemaParseChoice(ctxt, schema, child);
2210         child = child->next;
2211     } else if (IS_SCHEMA(child, "sequence")) {
2212         subtype = (xmlSchemaTypePtr)
2213               xmlSchemaParseSequence(ctxt, schema, child);
2214         child = child->next;
2215     }
2216     if (subtype != NULL)
2217         type->subtypes = subtype;
2218     if (child != NULL) {
2219         ctxt->nberrors++;
2220         xmlSchemaErrorContext(ctxt, schema, node, child);
2221         if ((ctxt != NULL) && (ctxt->error != NULL))
2222             ctxt->error(ctxt->userData,
2223                         "Group %s has unexpected content\n",
2224                         type->name);
2225     }
2226
2227     return (type);
2228 }
2229
2230 /**
2231  * xmlSchemaParseAll:
2232  * @ctxt:  a schema validation context
2233  * @schema:  the schema being built
2234  * @node:  a subtree containing XML Schema informations
2235  *
2236  * parse a XML schema All definition
2237  * *WARNING* this interface is highly subject to change
2238  *
2239  * Returns -1 in case of error, 0 if the declaration is inproper and
2240  *         1 in case of success.
2241  */
2242 static xmlSchemaTypePtr
2243 xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2244                           xmlNodePtr node)
2245 {
2246     xmlSchemaTypePtr type, subtype, last = NULL;
2247     xmlNodePtr child = NULL;
2248     xmlChar name[30];
2249
2250     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2251         return (NULL);
2252
2253
2254     snprintf((char *)name, 30, "all%d", ctxt->counter++ + 1);
2255     type = xmlSchemaAddType(ctxt, schema, name);
2256     if (type == NULL)
2257         return (NULL);
2258     type->node = node;
2259     type->type = XML_SCHEMA_TYPE_ALL;
2260     type->id = xmlGetProp(node, BAD_CAST "id");
2261     type->minOccurs = xmlGetMinOccurs(ctxt, node);
2262     type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2263
2264     child = node->children;
2265     if (IS_SCHEMA(child, "annotation")) {
2266         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2267         child = child->next;
2268     }
2269     while (IS_SCHEMA(child, "element")) {
2270         subtype = (xmlSchemaTypePtr) 
2271               xmlSchemaParseElement(ctxt, schema, child, 0);
2272         if (subtype != NULL) {
2273             if (last == NULL) {
2274                 type->subtypes = subtype;
2275                 last = subtype;
2276             } else {
2277                 last->next = subtype;
2278                 last = subtype;
2279             }
2280             last->next = NULL;
2281         }
2282         child = child->next;
2283     }
2284     if (child != NULL) {
2285         ctxt->nberrors++;
2286         xmlSchemaErrorContext(ctxt, schema, node, child);
2287         if ((ctxt != NULL) && (ctxt->error != NULL))
2288             ctxt->error(ctxt->userData,
2289                         "All %s has unexpected content\n",
2290                         type->name);
2291     }
2292
2293     return (type);
2294 }
2295
2296 /**
2297  * xmlSchemaParseImport:
2298  * @ctxt:  a schema validation context
2299  * @schema:  the schema being built
2300  * @node:  a subtree containing XML Schema informations
2301  *
2302  * parse a XML schema Import definition
2303  * *WARNING* this interface is highly subject to change
2304  *
2305  * Returns -1 in case of error, 0 if the declaration is inproper and
2306  *         1 in case of success.
2307  */
2308 static int
2309 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2310                           xmlNodePtr node)
2311 {
2312     xmlNodePtr child = NULL;
2313     xmlChar *namespace;
2314     xmlChar *schemaLocation;
2315     xmlChar *previous;
2316     xmlURIPtr check;
2317
2318     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2319         return (-1);
2320
2321     namespace = xmlGetProp(node, BAD_CAST "namespace");
2322     if (namespace != NULL) {
2323         check = xmlParseURI((const char *) namespace);
2324         if (check == NULL) {
2325             ctxt->nberrors++;
2326             xmlSchemaErrorContext(ctxt, schema, node, child);
2327             if ((ctxt != NULL) && (ctxt->error != NULL))
2328                 ctxt->error(ctxt->userData,
2329                             "Import namespace attribute is not an URI: %s\n",
2330                             namespace);
2331             xmlFree(namespace);
2332             return(-1);
2333         } else {
2334             xmlFreeURI(check);
2335         }
2336     }
2337     schemaLocation = xmlGetProp(node, BAD_CAST "schemaLocation");
2338     if (schemaLocation != NULL) {
2339         check = xmlParseURI((const char *) schemaLocation);
2340         if (check == NULL) {
2341             ctxt->nberrors++;
2342             xmlSchemaErrorContext(ctxt, schema, node, child);
2343             if ((ctxt != NULL) && (ctxt->error != NULL))
2344                 ctxt->error(ctxt->userData,
2345                     "Import schemaLocation attribute is not an URI: %s\n",
2346                             schemaLocation);
2347             if (namespace != NULL)
2348                 xmlFree(namespace);
2349             xmlFree(schemaLocation);
2350             return(-1);
2351         } else {
2352             xmlFreeURI(check);
2353         }
2354     }
2355     if (schema->schemasImports == NULL) {
2356         schema->schemasImports = xmlHashCreate(10);
2357         if (schema->schemasImports == NULL) {
2358             ctxt->nberrors++;
2359             xmlSchemaErrorContext(ctxt, schema, node, child);
2360             if ((ctxt != NULL) && (ctxt->error != NULL))
2361                 ctxt->error(ctxt->userData,
2362                     "Internal: failed to build import table\n");
2363             if (namespace != NULL)
2364                 xmlFree(namespace);
2365             if (schemaLocation != NULL)
2366                 xmlFree(schemaLocation);
2367             return(-1);
2368         }
2369     }
2370     if (namespace == NULL) {
2371         previous = xmlHashLookup(schema->schemasImports,
2372                 XML_SCHEMAS_DEFAULT_NAMESPACE);
2373         if (schemaLocation != NULL) {
2374             if (previous != NULL) {
2375                 if (!xmlStrEqual(schemaLocation, previous)) {
2376                     ctxt->nberrors++;
2377                     xmlSchemaErrorContext(ctxt, schema, node, child);
2378                     if ((ctxt != NULL) && (ctxt->error != NULL))
2379                         ctxt->error(ctxt->userData,
2380         "Redefining import for default namespace with a different URI: %s\n",
2381                                     schemaLocation);
2382                 }
2383             } else {
2384                 xmlHashAddEntry(schema->schemasImports, 
2385                         XML_SCHEMAS_DEFAULT_NAMESPACE, schemaLocation);
2386             }
2387         }
2388     } else {
2389         previous = xmlHashLookup(schema->schemasImports, namespace);
2390         if (schemaLocation != NULL) {
2391             if (previous != NULL) {
2392                 if (!xmlStrEqual(schemaLocation, previous)) {
2393                     ctxt->nberrors++;
2394                     xmlSchemaErrorContext(ctxt, schema, node, child);
2395                     if ((ctxt != NULL) && (ctxt->error != NULL))
2396                         ctxt->error(ctxt->userData,
2397         "Redefining import for namespace %s with a different URI: %s\n",
2398                                     namespace, schemaLocation);
2399                 }
2400             } else {
2401                 xmlHashAddEntry(schema->schemasImports, 
2402                         namespace, schemaLocation);
2403             }
2404         }
2405     }
2406
2407     child = node->children;
2408     while (IS_SCHEMA(child, "annotation")) {
2409         /*
2410          * the annotations here are simply discarded ...
2411          */
2412         child = child->next;
2413     }
2414     if (child != NULL) {
2415         ctxt->nberrors++;
2416         xmlSchemaErrorContext(ctxt, schema, node, child);
2417         if ((ctxt != NULL) && (ctxt->error != NULL))
2418             ctxt->error(ctxt->userData,
2419                         "Import has unexpected content\n");
2420         return(-1);
2421     }
2422     return(1);
2423 }
2424
2425 /**
2426  * xmlSchemaParseChoice:
2427  * @ctxt:  a schema validation context
2428  * @schema:  the schema being built
2429  * @node:  a subtree containing XML Schema informations
2430  *
2431  * parse a XML schema Choice definition
2432  * *WARNING* this interface is highly subject to change
2433  *
2434  * Returns -1 in case of error, 0 if the declaration is inproper and
2435  *         1 in case of success.
2436  */
2437 static xmlSchemaTypePtr
2438 xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2439                           xmlNodePtr node)
2440 {
2441     xmlSchemaTypePtr type, subtype, last = NULL;
2442     xmlNodePtr child = NULL;
2443     xmlChar name[30];
2444
2445     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2446         return (NULL);
2447
2448
2449     snprintf((char *)name, 30, "choice %d", ctxt->counter++ + 1);
2450     type = xmlSchemaAddType(ctxt, schema, name);
2451     if (type == NULL)
2452         return (NULL);
2453     type->node = node;
2454     type->type = XML_SCHEMA_TYPE_CHOICE;
2455     type->id = xmlGetProp(node, BAD_CAST "id");
2456     type->minOccurs = xmlGetMinOccurs(ctxt, node);
2457     type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2458
2459     child = node->children;
2460     if (IS_SCHEMA(child, "annotation")) {
2461         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2462         child = child->next;
2463     }
2464     while ((IS_SCHEMA(child, "element")) ||
2465            (IS_SCHEMA(child, "group")) ||
2466            (IS_SCHEMA(child, "any")) ||
2467            (IS_SCHEMA(child, "choice")) ||
2468            (IS_SCHEMA(child, "sequence"))) {
2469         subtype = NULL;
2470         if (IS_SCHEMA(child, "element")) {
2471             subtype = (xmlSchemaTypePtr) 
2472                   xmlSchemaParseElement(ctxt, schema, child, 0);
2473         } else if (IS_SCHEMA(child, "group")) {
2474             subtype = xmlSchemaParseGroup(ctxt, schema, child);
2475         } else if (IS_SCHEMA(child, "any")) {
2476             subtype = xmlSchemaParseAny(ctxt, schema, child);
2477         } else if (IS_SCHEMA(child, "sequence")) {
2478             subtype = xmlSchemaParseSequence(ctxt, schema, child);
2479         } else if (IS_SCHEMA(child, "choice")) {
2480             subtype = xmlSchemaParseChoice(ctxt, schema, child);
2481         }
2482         if (subtype != NULL) {
2483             if (last == NULL) {
2484                 type->subtypes = subtype;
2485                 last = subtype;
2486             } else {
2487                 last->next = subtype;
2488                 last = subtype;
2489             }
2490             last->next = NULL;
2491         }
2492         child = child->next;
2493     }
2494     if (child != NULL) {
2495         ctxt->nberrors++;
2496         xmlSchemaErrorContext(ctxt, schema, node, child);
2497         if ((ctxt != NULL) && (ctxt->error != NULL))
2498             ctxt->error(ctxt->userData,
2499                         "Choice %s has unexpected content\n",
2500                         type->name);
2501     }
2502
2503     return (type);
2504 }
2505
2506 /**
2507  * xmlSchemaParseSequence:
2508  * @ctxt:  a schema validation context
2509  * @schema:  the schema being built
2510  * @node:  a subtree containing XML Schema informations
2511  *
2512  * parse a XML schema Sequence definition
2513  * *WARNING* this interface is highly subject to change
2514  *
2515  * Returns -1 in case of error, 0 if the declaration is inproper and
2516  *         1 in case of success.
2517  */
2518 static xmlSchemaTypePtr
2519 xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2520                           xmlNodePtr node)
2521 {
2522     xmlSchemaTypePtr type, subtype, last = NULL;
2523     xmlNodePtr child = NULL;
2524     xmlChar name[30];
2525
2526     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2527         return (NULL);
2528
2529
2530     snprintf((char *)name, 30, "sequence %d", ctxt->counter++ + 1);
2531     type = xmlSchemaAddType(ctxt, schema, name);
2532     if (type == NULL)
2533         return (NULL);
2534     type->node = node;
2535     type->type = XML_SCHEMA_TYPE_SEQUENCE;
2536     type->id = xmlGetProp(node, BAD_CAST "id");
2537     type->minOccurs = xmlGetMinOccurs(ctxt, node);
2538     type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2539
2540     child = node->children;
2541     if (IS_SCHEMA(child, "annotation")) {
2542         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2543         child = child->next;
2544     }
2545     while ((IS_SCHEMA(child, "element")) ||
2546            (IS_SCHEMA(child, "group")) ||
2547            (IS_SCHEMA(child, "any")) ||
2548            (IS_SCHEMA(child, "choice")) ||
2549            (IS_SCHEMA(child, "sequence"))) {
2550         subtype = NULL;
2551         if (IS_SCHEMA(child, "element")) {
2552             subtype = (xmlSchemaTypePtr) 
2553                   xmlSchemaParseElement(ctxt, schema, child, 0);
2554         } else if (IS_SCHEMA(child, "group")) {
2555             subtype = xmlSchemaParseGroup(ctxt, schema, child);
2556         } else if (IS_SCHEMA(child, "any")) {
2557             subtype = xmlSchemaParseAny(ctxt, schema, child);
2558         } else if (IS_SCHEMA(child, "choice")) {
2559             subtype = xmlSchemaParseChoice(ctxt, schema, child);
2560         } else if (IS_SCHEMA(child, "sequence")) {
2561             subtype = xmlSchemaParseSequence(ctxt, schema, child);
2562         }
2563         if (subtype != NULL) {
2564             if (last == NULL) {
2565                 type->subtypes = subtype;
2566                 last = subtype;
2567             } else {
2568                 last->next = subtype;
2569                 last = subtype;
2570             }
2571             last->next = NULL;
2572         }
2573         child = child->next;
2574     }
2575     if (child != NULL) {
2576         ctxt->nberrors++;
2577         xmlSchemaErrorContext(ctxt, schema, node, child);
2578         if ((ctxt != NULL) && (ctxt->error != NULL))
2579             ctxt->error(ctxt->userData,
2580                         "Sequence %s has unexpected content\n",
2581                         type->name);
2582     }
2583
2584     return (type);
2585 }
2586
2587 /**
2588  * xmlSchemaParseRestriction:
2589  * @ctxt:  a schema validation context
2590  * @schema:  the schema being built
2591  * @node:  a subtree containing XML Schema informations
2592  * @simple:  is that part of a simple type.
2593  *
2594  * parse a XML schema Restriction definition
2595  * *WARNING* this interface is highly subject to change
2596  *
2597  * Returns the type definition or NULL in case of error
2598  */
2599 static xmlSchemaTypePtr
2600 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2601                           xmlNodePtr node, int simple)
2602 {
2603     xmlSchemaTypePtr type, subtype;
2604     xmlSchemaFacetPtr facet, lastfacet = NULL;
2605     xmlNodePtr child = NULL;
2606     xmlChar name[30];
2607     xmlChar *oldcontainer;
2608
2609     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2610         return (NULL);
2611
2612     oldcontainer = ctxt->container;
2613
2614     snprintf((char *)name, 30, "restriction %d", ctxt->counter++ + 1);
2615     type = xmlSchemaAddType(ctxt, schema, name);
2616     if (type == NULL)
2617         return (NULL);
2618     type->node = node;
2619     type->type = XML_SCHEMA_TYPE_RESTRICTION;
2620     type->id = xmlGetProp(node, BAD_CAST "id");
2621     type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2622     if ((!simple) && (type->base == NULL)) {
2623         ctxt->nberrors++;
2624         xmlSchemaErrorContext(ctxt, schema, node, child);
2625         if ((ctxt != NULL) && (ctxt->error != NULL))
2626             ctxt->error(ctxt->userData,
2627                         "Restriction %s has no base\n",
2628                         type->name);
2629     }
2630     ctxt->container = name;
2631
2632     child = node->children;
2633     if (IS_SCHEMA(child, "annotation")) {
2634         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2635         child = child->next;
2636     }
2637     subtype = NULL;
2638
2639     if (IS_SCHEMA(child, "all")) {
2640         subtype = (xmlSchemaTypePtr) 
2641               xmlSchemaParseAll(ctxt, schema, child);
2642         child = child->next;
2643         type->subtypes = subtype;
2644     } else if (IS_SCHEMA(child, "choice")) {
2645         subtype = xmlSchemaParseChoice(ctxt, schema, child);
2646         child = child->next;
2647         type->subtypes = subtype;
2648     } else if (IS_SCHEMA(child, "sequence")) {
2649         subtype = (xmlSchemaTypePtr) 
2650               xmlSchemaParseSequence(ctxt, schema, child);
2651         child = child->next;
2652         type->subtypes = subtype;
2653     } else if (IS_SCHEMA(child, "group")) {
2654         subtype = (xmlSchemaTypePtr) 
2655               xmlSchemaParseGroup(ctxt, schema, child);
2656         child = child->next;
2657         type->subtypes = subtype;
2658     } else {
2659         if (IS_SCHEMA(child, "simpleType")) {
2660             subtype = (xmlSchemaTypePtr) 
2661                   xmlSchemaParseSimpleType(ctxt, schema, child);
2662             child = child->next;
2663             type->baseType = subtype;
2664         }
2665         /*
2666          * Facets
2667          */
2668         while ((IS_SCHEMA(child, "minInclusive")) ||
2669                (IS_SCHEMA(child, "minExclusive")) ||
2670                (IS_SCHEMA(child, "maxInclusive")) ||
2671                (IS_SCHEMA(child, "maxExclusive")) ||
2672                (IS_SCHEMA(child, "totalDigits")) ||
2673                (IS_SCHEMA(child, "fractionDigits")) ||
2674                (IS_SCHEMA(child, "pattern")) ||
2675                (IS_SCHEMA(child, "enumeration")) ||
2676                (IS_SCHEMA(child, "whiteSpace")) ||
2677                (IS_SCHEMA(child, "length")) ||
2678                (IS_SCHEMA(child, "maxLength")) ||
2679                (IS_SCHEMA(child, "minLength"))) {
2680             facet = xmlSchemaParseFacet(ctxt, schema, child);
2681             if (facet != NULL) {
2682                 if (lastfacet == NULL) {
2683                     type->facets = facet;
2684                     lastfacet = facet;
2685                 } else {
2686                     lastfacet->next = facet;
2687                     lastfacet = facet;
2688                 }
2689                 lastfacet->next = NULL;
2690             }
2691             child = child->next;
2692         }
2693     }
2694     child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2695     if (child != NULL) {
2696         ctxt->nberrors++;
2697         xmlSchemaErrorContext(ctxt, schema, node, child);
2698         if ((ctxt != NULL) && (ctxt->error != NULL))
2699             ctxt->error(ctxt->userData,
2700                         "Restriction %s has unexpected content\n",
2701                         type->name);
2702     }
2703     ctxt->container = oldcontainer;
2704     return (type);
2705 }
2706
2707 /**
2708  * xmlSchemaParseExtension:
2709  * @ctxt:  a schema validation context
2710  * @schema:  the schema being built
2711  * @node:  a subtree containing XML Schema informations
2712  *
2713  * parse a XML schema Extension definition
2714  * *WARNING* this interface is highly subject to change
2715  *
2716  * Returns the type definition or NULL in case of error
2717  */
2718 static xmlSchemaTypePtr
2719 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2720                           xmlNodePtr node)
2721 {
2722     xmlSchemaTypePtr type, subtype;
2723     xmlNodePtr child = NULL;
2724     xmlChar name[30];
2725     xmlChar *oldcontainer;
2726
2727     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2728         return (NULL);
2729
2730     oldcontainer = ctxt->container;
2731
2732     snprintf((char *)name, 30, "extension %d", ctxt->counter++ + 1);
2733     type = xmlSchemaAddType(ctxt, schema, name);
2734     if (type == NULL)
2735         return (NULL);
2736     type->node = node;
2737     type->type = XML_SCHEMA_TYPE_EXTENSION;
2738     type->id = xmlGetProp(node, BAD_CAST "id");
2739     ctxt->container = name;
2740
2741     type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2742     if (type->base == NULL) {
2743         ctxt->nberrors++;
2744         xmlSchemaErrorContext(ctxt, schema, node, child);
2745         if ((ctxt != NULL) && (ctxt->error != NULL))
2746             ctxt->error(ctxt->userData,
2747                         "Extension %s has no base\n",
2748                         type->name);
2749     }
2750     child = node->children;
2751     if (IS_SCHEMA(child, "annotation")) {
2752         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2753         child = child->next;
2754     }
2755     subtype = NULL;
2756
2757     if (IS_SCHEMA(child, "all")) {
2758         subtype = xmlSchemaParseAll(ctxt, schema, child);
2759         child = child->next;
2760     } else if (IS_SCHEMA(child, "choice")) {
2761         subtype = xmlSchemaParseChoice(ctxt, schema, child);
2762         child = child->next;
2763     } else if (IS_SCHEMA(child, "sequence")) {
2764         subtype = xmlSchemaParseSequence(ctxt, schema, child);
2765         child = child->next;
2766     } else if (IS_SCHEMA(child, "group")) {
2767         subtype = xmlSchemaParseGroup(ctxt, schema, child);
2768         child = child->next;
2769     }
2770     if (subtype != NULL)
2771         type->subtypes = subtype;
2772     child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2773     if (child != NULL) {
2774         ctxt->nberrors++;
2775         xmlSchemaErrorContext(ctxt, schema, node, child);
2776         if ((ctxt != NULL) && (ctxt->error != NULL))
2777             ctxt->error(ctxt->userData,
2778                         "Extension %s has unexpected content\n",
2779                         type->name);
2780     }
2781     ctxt->container = oldcontainer;
2782     return (type);
2783 }
2784
2785 /**
2786  * xmlSchemaParseSimpleContent:
2787  * @ctxt:  a schema validation context
2788  * @schema:  the schema being built
2789  * @node:  a subtree containing XML Schema informations
2790  *
2791  * parse a XML schema SimpleContent definition
2792  * *WARNING* this interface is highly subject to change
2793  *
2794  * Returns the type definition or NULL in case of error
2795  */
2796 static xmlSchemaTypePtr
2797 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2798                           xmlNodePtr node)
2799 {
2800     xmlSchemaTypePtr type, subtype;
2801     xmlNodePtr child = NULL;
2802     xmlChar name[30];
2803
2804     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2805         return (NULL);
2806
2807
2808     snprintf((char *)name, 30, "complexContent %d", ctxt->counter++ + 1);
2809     type = xmlSchemaAddType(ctxt, schema, name);
2810     if (type == NULL)
2811         return (NULL);
2812     type->node = node;
2813     type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
2814     type->id = xmlGetProp(node, BAD_CAST "id");
2815
2816     child = node->children;
2817     if (IS_SCHEMA(child, "annotation")) {
2818         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2819         child = child->next;
2820     }
2821     subtype = NULL;
2822     if (IS_SCHEMA(child, "restriction")) {
2823         subtype = (xmlSchemaTypePtr) 
2824               xmlSchemaParseRestriction(ctxt, schema, child, 0);
2825         child = child->next;
2826     } else if (IS_SCHEMA(child, "extension")) {
2827         subtype = (xmlSchemaTypePtr) 
2828               xmlSchemaParseExtension(ctxt, schema, child);
2829         child = child->next;
2830     }
2831     type->subtypes = subtype;
2832     if (child != NULL) {
2833         ctxt->nberrors++;
2834         xmlSchemaErrorContext(ctxt, schema, node, child);
2835         if ((ctxt != NULL) && (ctxt->error != NULL))
2836             ctxt->error(ctxt->userData,
2837                         "SimpleContent %s has unexpected content\n",
2838                         type->name);
2839     }
2840     return (type);
2841 }
2842
2843 /**
2844  * xmlSchemaParseComplexContent:
2845  * @ctxt:  a schema validation context
2846  * @schema:  the schema being built
2847  * @node:  a subtree containing XML Schema informations
2848  *
2849  * parse a XML schema ComplexContent definition
2850  * *WARNING* this interface is highly subject to change
2851  *
2852  * Returns the type definition or NULL in case of error
2853  */
2854 static xmlSchemaTypePtr
2855 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2856                           xmlNodePtr node)
2857 {
2858     xmlSchemaTypePtr type, subtype;
2859     xmlNodePtr child = NULL;
2860     xmlChar name[30];
2861
2862     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2863         return (NULL);
2864
2865
2866     snprintf((char *)name, 30, "complexContent %d", ctxt->counter++ + 1);
2867     type = xmlSchemaAddType(ctxt, schema, name);
2868     if (type == NULL)
2869         return (NULL);
2870     type->node = node;
2871     type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
2872     type->id = xmlGetProp(node, BAD_CAST "id");
2873
2874     child = node->children;
2875     if (IS_SCHEMA(child, "annotation")) {
2876         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2877         child = child->next;
2878     }
2879     subtype = NULL;
2880     if (IS_SCHEMA(child, "restriction")) {
2881         subtype = (xmlSchemaTypePtr) 
2882               xmlSchemaParseRestriction(ctxt, schema, child, 0);
2883         child = child->next;
2884     } else if (IS_SCHEMA(child, "extension")) {
2885         subtype = (xmlSchemaTypePtr) 
2886               xmlSchemaParseExtension(ctxt, schema, child);
2887         child = child->next;
2888     }
2889     type->subtypes = subtype;
2890     if (child != NULL) {
2891         ctxt->nberrors++;
2892         xmlSchemaErrorContext(ctxt, schema, node, child);
2893         if ((ctxt != NULL) && (ctxt->error != NULL))
2894             ctxt->error(ctxt->userData,
2895                         "ComplexContent %s has unexpected content\n",
2896                         type->name);
2897     }
2898     return (type);
2899 }
2900
2901 /**
2902  * xmlSchemaParseComplexType:
2903  * @ctxt:  a schema validation context
2904  * @schema:  the schema being built
2905  * @node:  a subtree containing XML Schema informations
2906  *
2907  * parse a XML schema Complex Type definition
2908  * *WARNING* this interface is highly subject to change
2909  *
2910  * Returns the type definition or NULL in case of error
2911  */
2912 static xmlSchemaTypePtr
2913 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2914                           xmlNodePtr node)
2915 {
2916     xmlSchemaTypePtr type, subtype;
2917     xmlNodePtr child = NULL;
2918     xmlChar *name;
2919     xmlChar *oldcontainer;
2920
2921     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2922         return (NULL);
2923
2924     oldcontainer = ctxt->container;
2925     name = xmlGetProp(node, (const xmlChar *) "name");
2926     if (name == NULL) {
2927         char buf[100];
2928
2929         snprintf(buf, 99, "anontype%d", ctxt->counter++ + 1);
2930         name = xmlStrdup((xmlChar *) buf);
2931     }
2932     if (name == NULL) {
2933         ctxt->nberrors++;
2934         xmlSchemaErrorContext(ctxt, schema, node, child);
2935         if ((ctxt != NULL) && (ctxt->error != NULL))
2936             ctxt->error(ctxt->userData, "complexType has no name\n");
2937         return (NULL);
2938     }
2939     type = xmlSchemaAddType(ctxt, schema, name);
2940     if (type == NULL) {
2941         xmlFree(name);
2942         return (NULL);
2943     }
2944     type->node = node;
2945     type->type = XML_SCHEMA_TYPE_COMPLEX;
2946     type->id = xmlGetProp(node, BAD_CAST "id");
2947     ctxt->container = name;
2948
2949     child = node->children;
2950     if (IS_SCHEMA(child, "annotation")) {
2951         type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2952         child = child->next;
2953     }
2954     if (IS_SCHEMA(child, "simpleContent")) {
2955         type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
2956         child = child->next;
2957     } else if (IS_SCHEMA(child, "complexContent")) {
2958         type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
2959         child = child->next;
2960     } else {
2961         subtype = NULL;
2962
2963         if (IS_SCHEMA(child, "all")) {
2964             subtype = xmlSchemaParseAll(ctxt, schema, child);
2965             child = child->next;
2966         } else if (IS_SCHEMA(child, "choice")) {
2967             subtype = xmlSchemaParseChoice(ctxt, schema, child);
2968             child = child->next;
2969         } else if (IS_SCHEMA(child, "sequence")) {
2970             subtype = xmlSchemaParseSequence(ctxt, schema, child);
2971             child = child->next;
2972         } else if (IS_SCHEMA(child, "group")) {
2973             subtype = xmlSchemaParseGroup(ctxt, schema, child);
2974             child = child->next;
2975         }
2976         if (subtype != NULL)
2977             type->subtypes = subtype;
2978         child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2979     }
2980     if (child != NULL) {
2981         ctxt->nberrors++;
2982         xmlSchemaErrorContext(ctxt, schema, node, child);
2983         if ((ctxt != NULL) && (ctxt->error != NULL))
2984             ctxt->error(ctxt->userData,
2985                         "ComplexType %s has unexpected content\n",
2986                         type->name);
2987     }
2988     ctxt->container = oldcontainer;
2989     xmlFree(name);
2990     return (type);
2991 }
2992
2993
2994 /**
2995  * xmlSchemaParseSchema:
2996  * @ctxt:  a schema validation context
2997  * @node:  a subtree containing XML Schema informations
2998  *
2999  * parse a XML schema definition from a node set
3000  * *WARNING* this interface is highly subject to change
3001  *
3002  * Returns the internal XML Schema structure built from the resource or
3003  *         NULL in case of error
3004  */
3005 static xmlSchemaPtr
3006 xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3007 {
3008     xmlSchemaPtr schema = NULL;
3009     xmlSchemaAnnotPtr annot;
3010     xmlNodePtr child = NULL;
3011     xmlChar *val;
3012     int nberrors;
3013
3014     if ((ctxt == NULL) || (node == NULL))
3015         return (NULL);
3016
3017     nberrors = ctxt->nberrors;
3018     ctxt->nberrors = 0;
3019     if (IS_SCHEMA(node, "schema")) {
3020         schema = xmlSchemaNewSchema(ctxt);
3021         if (schema == NULL)
3022             return(NULL);
3023         schema->targetNamespace = xmlGetProp(node, BAD_CAST "targetNamespace");
3024         schema->id = xmlGetProp(node, BAD_CAST "id");
3025         schema->version = xmlGetProp(node, BAD_CAST "version");
3026         val = xmlGetProp(node, BAD_CAST "elementFormDefault");
3027         if (val != NULL) {
3028             if (xmlStrEqual(val, BAD_CAST "qualified"))
3029                 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3030             else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3031                 ctxt->nberrors++;
3032                 xmlSchemaErrorContext(ctxt, schema, node, child);
3033                 if ((ctxt != NULL) && (ctxt->error != NULL)) {
3034                     ctxt->error(ctxt->userData,
3035                                 "Invalid value %s for elementFormDefault\n",
3036                                 val);
3037                 }
3038             }
3039             xmlFree(val);
3040         }
3041         val = xmlGetProp(node, BAD_CAST "attributeFormDefault");
3042         if (val != NULL) {
3043             if (xmlStrEqual(val, BAD_CAST "qualified"))
3044                 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3045             else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3046                 ctxt->nberrors++;
3047                 xmlSchemaErrorContext(ctxt, schema, node, child);
3048                 if ((ctxt != NULL) && (ctxt->error != NULL)) {
3049                     ctxt->error(ctxt->userData,
3050                                 "Invalid value %s for elementFormDefault\n",
3051                                 val);
3052                 }
3053             }
3054             xmlFree(val);
3055         }
3056
3057         child = node->children;
3058         while ((IS_SCHEMA(child, "include")) ||
3059                (IS_SCHEMA(child, "import")) ||
3060                (IS_SCHEMA(child, "redefine")) ||
3061                (IS_SCHEMA(child, "annotation"))) {
3062             if (IS_SCHEMA(child, "annotation")) {
3063                 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3064                 if (schema->annot == NULL)
3065                     schema->annot = annot;
3066                 else
3067                     xmlSchemaFreeAnnot(annot);
3068             } else if (IS_SCHEMA(child, "include")) {
3069                 TODO
3070             } else if (IS_SCHEMA(child, "import")) {
3071                 xmlSchemaParseImport(ctxt, schema, child);
3072             } else if (IS_SCHEMA(child, "redefine")) {
3073                 TODO
3074             }
3075             child = child->next;
3076         }
3077         while (child != NULL) {
3078             if (IS_SCHEMA(child, "complexType")) {
3079                 xmlSchemaParseComplexType(ctxt, schema, child);
3080                 child = child->next;
3081             } else if (IS_SCHEMA(child, "simpleType")) {
3082                 xmlSchemaParseSimpleType(ctxt, schema, child);
3083                 child = child->next;
3084             } else if (IS_SCHEMA(child, "element")) {
3085                 xmlSchemaParseElement(ctxt, schema, child, 1);
3086                 child = child->next;
3087             } else if (IS_SCHEMA(child, "attribute")) {
3088                 xmlSchemaParseAttribute(ctxt, schema, child);
3089                 child = child->next;
3090             } else if (IS_SCHEMA(child, "attributeGroup")) {
3091                 xmlSchemaParseAttributeGroup(ctxt, schema, child);
3092                 child = child->next;
3093             } else if (IS_SCHEMA(child, "group")) {
3094                 xmlSchemaParseGroup(ctxt, schema, child);
3095                 child = child->next;
3096             } else if (IS_SCHEMA(child, "notation")) {
3097                 xmlSchemaParseNotation(ctxt, schema, child);
3098                 child = child->next;
3099             } else {
3100                 ctxt->nberrors++;
3101                 xmlSchemaErrorContext(ctxt, schema, node, child);
3102                 if ((ctxt != NULL) && (ctxt->error != NULL))
3103                     ctxt->error(ctxt->userData,
3104                                 "Schemas: unexpected element %s here \n",
3105                                 child->name);
3106                 child = child->next;
3107             }
3108             while (IS_SCHEMA(child, "annotation")) {
3109                 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3110                 if (schema->annot == NULL)
3111                     schema->annot = annot;
3112                 else
3113                     xmlSchemaFreeAnnot(annot);
3114                 child = child->next;
3115             }
3116         }
3117     }
3118     if (ctxt->nberrors != 0) {
3119         if (schema != NULL) {
3120             xmlSchemaFree(schema);
3121             schema = NULL;
3122         }
3123     }
3124     ctxt->nberrors = nberrors;
3125 #ifdef DEBUG
3126     if (schema == NULL)
3127         xmlGenericError(xmlGenericErrorContext,
3128                         "xmlSchemaParse() failed\n");
3129 #endif
3130
3131     return (schema);
3132 }
3133
3134 /************************************************************************
3135  *                                                                      *
3136  *                      Validating using Schemas                        *
3137  *                                                                      *
3138  ************************************************************************/
3139
3140 /************************************************************************
3141  *                                                                      *
3142  *                      Reading/Writing Schemas                         *
3143  *                                                                      *
3144  ************************************************************************/
3145
3146 /**
3147  * xmlSchemaNewParserCtxt:
3148  * @URL:  the location of the schema
3149  *
3150  * Create an XML Schemas parse context for that file/resource expected
3151  * to contain an XML Schemas file.
3152  *
3153  * Returns the parser context or NULL in case of error
3154  */
3155 xmlSchemaParserCtxtPtr
3156 xmlSchemaNewParserCtxt(const char *URL) {
3157     xmlSchemaParserCtxtPtr ret;
3158
3159     if (URL == NULL)
3160         return(NULL);
3161
3162     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3163     if (ret == NULL) {
3164         xmlGenericError(xmlGenericErrorContext,
3165                 "Failed to allocate new schama parser context for %s\n", URL);
3166         return (NULL);
3167     }
3168     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3169     ret->URL = xmlStrdup((const xmlChar *)URL);
3170     return (ret);
3171 }
3172
3173 /**
3174  * xmlSchemaNewMemParserCtxt:
3175  * @buffer:  a pointer to a char array containing the schemas
3176  * @size:  the size of the array
3177  *
3178  * Create an XML Schemas parse context for that memory buffer expected
3179  * to contain an XML Schemas file.
3180  *
3181  * Returns the parser context or NULL in case of error
3182  */
3183 xmlSchemaParserCtxtPtr
3184 xmlSchemaNewMemParserCtxt(const char *buffer, int size) {
3185     xmlSchemaParserCtxtPtr ret;
3186
3187     if ((buffer == NULL) || (size <= 0))
3188         return(NULL);
3189
3190     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3191     if (ret == NULL) {
3192         xmlGenericError(xmlGenericErrorContext,
3193                 "Failed to allocate new schama parser context\n");
3194         return (NULL);
3195     }
3196     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3197     ret->buffer = buffer;
3198     ret->size = size;
3199     return (ret);
3200 }
3201
3202 /**
3203  * xmlSchemaFreeParserCtxt:
3204  * @ctxt:  the schema parser context
3205  *
3206  * Free the resources associated to the schema parser context
3207  */
3208 void
3209 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) {
3210     if (ctxt == NULL)
3211         return;
3212     if (ctxt->URL != NULL)
3213         xmlFree(ctxt->URL);
3214     if (ctxt->doc != NULL)
3215         xmlFreeDoc(ctxt->doc);
3216     xmlFree(ctxt);
3217 }
3218
3219 /************************************************************************
3220  *                                                                      *
3221  *                      Building the content models                     *
3222  *                                                                      *
3223  ************************************************************************/
3224 /**
3225  * xmlSchemaBuildAContentModel:
3226  * @type:  the schema type definition
3227  * @ctxt:  the schema parser context
3228  * @name:  the element name whose content is being built
3229  *
3230  * Generate the automata sequence needed for that type
3231  */
3232 static void
3233 xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
3234                            xmlSchemaParserCtxtPtr ctxt,
3235                            const xmlChar *name) {
3236     if (type == NULL) {
3237         xmlGenericError(xmlGenericErrorContext,
3238                 "Found unexpected type = NULL in %s content model\n",
3239                         name);
3240         return;
3241     }
3242     switch (type->type) {
3243         case XML_SCHEMA_TYPE_ANY:
3244             /* TODO : handle the namespace too */
3245             /* TODO : make that a specific transition type */
3246             TODO
3247             ctxt->state = xmlAutomataNewTransition(ctxt->am, ctxt->state,
3248                                 NULL, BAD_CAST "*", NULL);
3249             break;
3250         case XML_SCHEMA_TYPE_ELEMENT: {
3251             xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3252             /* TODO : handle the namespace too */
3253             xmlAutomataStatePtr oldstate = ctxt->state;
3254             if (elem->maxOccurs >= UNBOUNDED) {
3255                 if (elem->minOccurs > 1) {
3256                     xmlAutomataStatePtr tmp;
3257                     int counter;
3258
3259                     ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3260                                                         oldstate, NULL);
3261                     oldstate = ctxt->state;
3262
3263                     counter = xmlAutomataNewCounter(ctxt->am,
3264                                     elem->minOccurs - 1, UNBOUNDED);
3265
3266                     if (elem->refDecl != NULL) {
3267                         xmlSchemaBuildAContentModel(
3268                                 (xmlSchemaTypePtr) elem->refDecl,
3269                                 ctxt, elem->refDecl->name);
3270                     } else {
3271                         ctxt->state = xmlAutomataNewTransition(ctxt->am,
3272                                 ctxt->state, NULL, elem->name, type);
3273                     }
3274                     tmp = ctxt->state;
3275                     xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3276                                                counter);
3277                     ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3278                                                NULL, counter);
3279
3280                 } else {
3281                     if (elem->refDecl != NULL) {
3282                         xmlSchemaBuildAContentModel(
3283                                 (xmlSchemaTypePtr) elem->refDecl,
3284                                 ctxt, elem->refDecl->name);
3285                     } else {
3286                         ctxt->state = xmlAutomataNewTransition(ctxt->am,
3287                                 ctxt->state, NULL, elem->name, type);
3288                     }
3289                     xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
3290                     if (elem->minOccurs == 0) {
3291                         /* basically an elem* */
3292                         xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3293                     }
3294                 }
3295             } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3296                 xmlAutomataStatePtr tmp;
3297                 int counter;
3298
3299                 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3300                                                     oldstate, NULL);
3301                 oldstate = ctxt->state;
3302
3303                 counter = xmlAutomataNewCounter(ctxt->am,
3304                                 elem->minOccurs - 1, elem->maxOccurs - 1);
3305
3306                 if (elem->refDecl != NULL) {
3307                     xmlSchemaBuildAContentModel(
3308                             (xmlSchemaTypePtr) elem->refDecl,
3309                             ctxt, elem->refDecl->name);
3310                 } else {
3311                     ctxt->state = xmlAutomataNewTransition(ctxt->am,
3312                             ctxt->state, NULL, elem->name, type);
3313                 }
3314                 tmp = ctxt->state;
3315                 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3316                                            counter);
3317                 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3318                                            NULL, counter);
3319                 if (elem->minOccurs == 0) {
3320                     /* basically an elem? */
3321                     xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3322                 }
3323
3324             } else {
3325                 if (elem->refDecl != NULL) {
3326                     xmlSchemaBuildAContentModel(
3327                             (xmlSchemaTypePtr) elem->refDecl,
3328                             ctxt, elem->refDecl->name);
3329                 } else {
3330                     ctxt->state = xmlAutomataNewTransition(ctxt->am,
3331                             ctxt->state, NULL, elem->name, type);
3332                 }
3333                 if (elem->minOccurs == 0) {
3334                     /* basically an elem? */
3335                     xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3336                 }
3337             }
3338             break;
3339         }
3340         case XML_SCHEMA_TYPE_SEQUENCE: {
3341             xmlSchemaTypePtr subtypes;
3342
3343             /*
3344              * If max and min occurances are default (1) then
3345              * simply iterate over the subtypes
3346              */
3347             if ((type->minOccurs == 1 ) && (type->maxOccurs == 1)) {
3348                 subtypes = type->subtypes;
3349                 while (subtypes != NULL) {
3350                     xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3351                     subtypes = subtypes->next;
3352                 }
3353             } else {
3354                 xmlAutomataStatePtr oldstate = ctxt->state;
3355                 if (type->maxOccurs >= UNBOUNDED) {
3356                     if (type->minOccurs > 1) {
3357                         xmlAutomataStatePtr tmp;
3358                         int counter;
3359
3360                         ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3361                                                         oldstate, NULL);
3362                         oldstate = ctxt->state;
3363
3364                         counter = xmlAutomataNewCounter(ctxt->am,
3365                                             type->minOccurs - 1, UNBOUNDED);
3366
3367                         subtypes = type->subtypes;
3368                         while (subtypes != NULL) {
3369                             xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3370                             subtypes = subtypes->next;
3371                         }
3372                         tmp = ctxt->state;
3373                         xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3374                                             counter);
3375                         ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3376                                             NULL, counter);
3377
3378                     } else {
3379                         subtypes = type->subtypes;
3380                         while (subtypes != NULL) {
3381                             xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3382                             subtypes = subtypes->next;
3383                         }
3384                         xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
3385                         if (type->minOccurs == 0) {
3386                             xmlAutomataNewEpsilon(ctxt->am, oldstate,
3387                                                   ctxt->state);
3388                         }
3389                     }
3390                 } else if ((type->maxOccurs > 1) || (type->minOccurs > 1)) {
3391                     xmlAutomataStatePtr tmp;
3392                     int counter;
3393
3394                     ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3395                                                     oldstate, NULL);
3396                     oldstate = ctxt->state;
3397
3398                     counter = xmlAutomataNewCounter(ctxt->am,
3399                                   type->minOccurs - 1, type->maxOccurs - 1);
3400
3401                     subtypes = type->subtypes;
3402                     while (subtypes&n