added Info.plist
[TestXSLT.git] / libxml2 / 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 != NULL) {
3403                         xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3404                         subtypes = subtypes->next;
3405                     }
3406                     tmp = ctxt->state;
3407                     xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3408                           counter);
3409                     ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3410                                                              NULL, counter);
3411                     if (type->minOccurs == 0) {
3412                         xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3413                     }
3414
3415                 } else {
3416                     subtypes = type->subtypes;
3417                     while (subtypes != NULL) {
3418                         xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3419                         subtypes = subtypes->next;
3420                     }
3421                     if (type->minOccurs == 0) {
3422                         xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3423                     }
3424                 }
3425             }
3426             break;
3427         }
3428         case XML_SCHEMA_TYPE_CHOICE: {
3429             xmlSchemaTypePtr subtypes;
3430             xmlAutomataStatePtr start, end;
3431
3432             start = ctxt->state;
3433             end = xmlAutomataNewState(ctxt->am);
3434
3435             /*
3436              * iterate over the subtypes and remerge the end with an
3437              * epsilon transition
3438              */
3439             if (type->maxOccurs == 1) {
3440                 subtypes = type->subtypes;
3441                 while (subtypes != NULL) {
3442                     ctxt->state = start;
3443                     xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3444                     xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
3445                     subtypes = subtypes->next;
3446                 }
3447             } else {
3448                 int counter;
3449                 xmlAutomataStatePtr hop;
3450                 int maxOccurs = type->maxOccurs == UNBOUNDED ?
3451                                       UNBOUNDED : type->maxOccurs - 1;
3452                 int minOccurs = type->minOccurs < 1 ? 0 : type->minOccurs - 1;
3453
3454                 /*
3455                  * use a counter to keep track of the number of transtions
3456                  * which went through the choice.
3457                  */
3458                 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
3459                 hop = xmlAutomataNewState(ctxt->am);
3460
3461                 subtypes = type->subtypes;
3462                 while (subtypes != NULL) {
3463                     ctxt->state = start;
3464                     xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3465                     xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
3466                     subtypes = subtypes->next;
3467                 }
3468                 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
3469                 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
3470             }
3471             if (type->minOccurs == 0) {
3472                 xmlAutomataNewEpsilon(ctxt->am, start, end);
3473             }
3474             ctxt->state = end;
3475             break;
3476         }
3477         case XML_SCHEMA_TYPE_ALL: {
3478             xmlAutomataStatePtr start;
3479             xmlSchemaTypePtr subtypes;
3480             xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3481             int lax;
3482
3483             subtypes = type->subtypes;
3484             if (subtypes == NULL)
3485                 break;
3486             start = ctxt->state;
3487             while (subtypes != NULL) {
3488                 ctxt->state = start;
3489                 elem = (xmlSchemaElementPtr) subtypes;
3490
3491                 /* TODO : handle the namespace too */
3492                 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
3493                     xmlAutomataNewOnceTrans(ctxt->am, ctxt->state, ctxt->state,
3494                                     elem->name, 1, 1, subtypes);
3495                 } else {
3496                     xmlAutomataNewCountTrans(ctxt->am, ctxt->state, ctxt->state,
3497                                     elem->name, elem->minOccurs,
3498                                     elem->maxOccurs, subtypes);
3499                 }
3500                 subtypes = subtypes->next;
3501             }
3502             lax = type->minOccurs == 0;
3503             ctxt->state = xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
3504                                                  lax);
3505             break;
3506         }
3507         case XML_SCHEMA_TYPE_RESTRICTION:
3508             if (type->subtypes != NULL)
3509                 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3510             break;
3511         case XML_SCHEMA_TYPE_EXTENSION:
3512             if (type->baseType != NULL) {
3513                 xmlSchemaTypePtr subtypes;
3514
3515                 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
3516                 subtypes = type->subtypes;
3517                 while (subtypes != NULL) {
3518                     xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3519                     subtypes = subtypes->next;
3520                 }
3521             } else if (type->subtypes != NULL)
3522                 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3523             break;
3524         case XML_SCHEMA_TYPE_GROUP:
3525             if (type->subtypes == NULL) {
3526             }
3527         case XML_SCHEMA_TYPE_COMPLEX:
3528         case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
3529             if (type->subtypes != NULL)
3530                 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3531             break;
3532         default:
3533             xmlGenericError(xmlGenericErrorContext,
3534                     "Found unexpected type %d in %s content model\n",
3535                             type->type, name);
3536             return;
3537     }
3538 }
3539 /**
3540  * xmlSchemaBuildContentModel:
3541  * @elem:  the element
3542  * @ctxt:  the schema parser context
3543  * @name:  the element name
3544  *
3545  * Builds the content model of the element.
3546  */
3547 static void
3548 xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
3549                            xmlSchemaParserCtxtPtr ctxt,
3550                            const xmlChar *name) {
3551     xmlAutomataStatePtr start;
3552
3553     if (elem->contModel != NULL)
3554         return;
3555     if (elem->subtypes == NULL) {
3556         elem->contentType = XML_SCHEMA_CONTENT_ANY;
3557         return;
3558     }
3559     if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
3560         return;
3561     if (elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC)
3562         return;
3563
3564 #ifdef DEBUG_CONTENT
3565     xmlGenericError(xmlGenericErrorContext,
3566             "Building content model for %s\n", name);
3567 #endif
3568
3569     ctxt->am = xmlNewAutomata();
3570     if (ctxt->am == NULL) {
3571         xmlGenericError(xmlGenericErrorContext,
3572                 "Cannot create automata for elem %s\n", name);
3573         return;
3574     }
3575     start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3576     xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3577     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
3578     elem->contModel = xmlAutomataCompile(ctxt->am);
3579     if (elem->contModel == NULL) {
3580         xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3581         if ((ctxt != NULL) && (ctxt->error != NULL))
3582             ctxt->error(ctxt->userData,
3583                         "failed to compile %s content model\n",
3584                         name);
3585         ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
3586         ctxt->nberrors++;
3587     } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
3588         xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3589         if ((ctxt != NULL) && (ctxt->error != NULL))
3590             ctxt->error(ctxt->userData,
3591                         "Content model of %s is not determinist:\n", name);
3592         ctxt->err = XML_SCHEMAS_ERR_NOTDETERMINIST;
3593         ctxt->nberrors++;
3594     } else {
3595 #ifdef DEBUG_CONTENT_REGEXP
3596         xmlGenericError(xmlGenericErrorContext,
3597                         "Content model of %s:\n", name);
3598         xmlRegexpPrint(stderr, elem->contModel);
3599 #endif
3600     }
3601     ctxt->state = NULL;
3602     xmlFreeAutomata(ctxt->am);
3603     ctxt->am = NULL;
3604 }
3605
3606 /**
3607  * xmlSchemaRefFixupCallback:
3608  * @elem:  the schema element context
3609  * @ctxt:  the schema parser context
3610  *
3611  * Free the resources associated to the schema parser context
3612  */
3613 static void
3614 xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
3615                      xmlSchemaParserCtxtPtr ctxt,
3616                      const xmlChar *name,
3617                      const xmlChar *context ATTRIBUTE_UNUSED,
3618                      const xmlChar *namespace ATTRIBUTE_UNUSED)
3619 {
3620     if ((ctxt == NULL) || (elem == NULL))
3621         return;
3622     if (elem->ref != NULL) {
3623         xmlSchemaElementPtr elemDecl;
3624
3625         if (elem->subtypes != NULL) {
3626             ctxt->nberrors++;
3627             xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3628             if ((ctxt != NULL) && (ctxt->error != NULL))
3629                 ctxt->error(ctxt->userData,
3630                             "Schemas: element %s have both ref and subtype\n",
3631                             name);
3632             return;
3633         }
3634         elemDecl = xmlHashLookup2(ctxt->schema->elemDecl,
3635                                   elem->ref, elem->refNs);
3636
3637         if (elemDecl == NULL) {
3638             ctxt->nberrors++;
3639             xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3640             if ((ctxt != NULL) && (ctxt->error != NULL))
3641                 ctxt->error(ctxt->userData,
3642                             "Schemas: element %s ref to %s not found\n",
3643                             name, elem->ref);
3644             return;
3645         }
3646         elem->refDecl = elemDecl;
3647     } else if (elem->namedType != NULL) {
3648         xmlSchemaTypePtr typeDecl;
3649
3650         if (elem->subtypes != NULL) {
3651             ctxt->nberrors++;
3652             xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3653             if ((ctxt != NULL) && (ctxt->error != NULL))
3654                 ctxt->error(ctxt->userData,
3655                             "Schemas: element %s have both type and subtype\n",
3656                             name);
3657             return;
3658         }
3659         typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3660                                     elem->namedTypeNs);
3661
3662         if (typeDecl == NULL) {
3663             ctxt->nberrors++;
3664             xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3665             if ((ctxt != NULL) && (ctxt->error != NULL))
3666                 ctxt->error(ctxt->userData,
3667                             "Schemas: element %s type %s not found\n",
3668                             name, elem->namedType);
3669             return;
3670         }
3671         elem->subtypes = typeDecl;
3672     }
3673 }
3674
3675 /**
3676  * xmlSchemaTypeFixup:
3677  * @typeDecl:  the schema type definition
3678  * @ctxt:  the schema parser context
3679  *
3680  * Fixes the content model of the type.
3681  */
3682 static void
3683 xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
3684                    xmlSchemaParserCtxtPtr ctxt,
3685                    const xmlChar *name)
3686 {
3687     if (typeDecl == NULL)
3688         return;
3689     if (name == NULL)
3690         name = typeDecl->name;
3691     if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
3692         switch (typeDecl->type) {
3693             case XML_SCHEMA_TYPE_SIMPLE_CONTENT: {
3694                 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3695                 if (typeDecl->subtypes != NULL)
3696                     typeDecl->contentType = typeDecl->subtypes->contentType;
3697                 break;
3698             }
3699             case XML_SCHEMA_TYPE_RESTRICTION: {
3700                 if (typeDecl->subtypes != NULL)
3701                     xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3702
3703                 if (typeDecl->base != NULL) {
3704                     xmlSchemaTypePtr baseType;
3705
3706                     baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3707                                                 typeDecl->baseNs);
3708                     if (baseType == NULL) {
3709                         ctxt->nberrors++;
3710                         if ((ctxt != NULL) && (ctxt->error != NULL))
3711                             ctxt->error(ctxt->userData,
3712                                 "Schemas: type %s base type %s not found\n",
3713                                         name, typeDecl->base);
3714                     }
3715                     typeDecl->baseType = baseType;
3716                 }
3717                 if (typeDecl->subtypes == NULL)
3718                     /* 1.1.1 */
3719                     typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3720                 else if ((typeDecl->subtypes->subtypes == NULL) &&
3721                     ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3722                      (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3723                     /* 1.1.2 */
3724                     typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3725                 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3726                     (typeDecl->subtypes->subtypes == NULL))
3727                     /* 1.1.3 */
3728                     typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3729                 else {
3730                     /* 1.2 and 2.X are applied at the other layer */
3731                     typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3732                 }
3733                 break;
3734             }
3735             case XML_SCHEMA_TYPE_EXTENSION: {
3736                 xmlSchemaContentType explicitContentType;
3737                 xmlSchemaTypePtr base;
3738
3739                 if (typeDecl->base != NULL) {
3740                     xmlSchemaTypePtr baseType;
3741
3742                     baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3743                                                 typeDecl->baseNs);
3744                     if (baseType == NULL) {
3745                         ctxt->nberrors++;
3746                         if ((ctxt != NULL) && (ctxt->error != NULL))
3747                             ctxt->error(ctxt->userData,
3748                                 "Schemas: type %s base type %s not found\n",
3749                                         name, typeDecl->base);
3750                     }
3751                     typeDecl->baseType = baseType;
3752                 }
3753                 if (typeDecl->subtypes != NULL)
3754                     xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3755
3756                 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
3757                 if (typeDecl->subtypes == NULL)
3758                     /* 1.1.1 */
3759                     explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3760                 else if ((typeDecl->subtypes->subtypes == NULL) &&
3761                     ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3762                      (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3763                     /* 1.1.2 */
3764                     explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3765                 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3766                     (typeDecl->subtypes->subtypes == NULL))
3767                     /* 1.1.3 */
3768                     explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3769
3770                 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3771                                         typeDecl->baseNs);
3772                 if (base == NULL) {
3773                     ctxt->nberrors++;
3774                     xmlSchemaErrorContext(ctxt, NULL, typeDecl->node, NULL);
3775                     if ((ctxt != NULL) && (ctxt->error != NULL))
3776                         ctxt->error(ctxt->userData,
3777                         "Schemas: base type %s of type %s not found\n",
3778                                     typeDecl->base, name);
3779                     return;
3780                 }
3781                 xmlSchemaTypeFixup(base, ctxt, NULL);
3782                 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
3783                     /* 2.1 */
3784                     typeDecl->contentType = base->contentType;
3785                 } else if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
3786                     /* 2.2 imbitable ! */
3787                     typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3788                 } else {
3789                     /* 2.3 imbitable pareil ! */
3790                     typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3791                 }
3792                 break;
3793             }
3794             case XML_SCHEMA_TYPE_COMPLEX: {
3795                 if (typeDecl->subtypes == NULL) {
3796                     typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3797                 } else {
3798                     if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3799                         typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3800                     else {
3801                         xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3802                         if (typeDecl->subtypes != NULL)
3803                             typeDecl->contentType =
3804                                     typeDecl->subtypes->contentType;
3805                     }
3806                 }
3807                 break;
3808             }
3809             case XML_SCHEMA_TYPE_COMPLEX_CONTENT: {
3810                 if (typeDecl->subtypes == NULL) {
3811                     typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3812                 } else {
3813                     if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3814                         typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3815                     else {
3816                         xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3817                         if (typeDecl->subtypes != NULL)
3818                             typeDecl->contentType =
3819                                     typeDecl->subtypes->contentType;
3820                     }
3821                 }
3822                 break;
3823             }
3824             case XML_SCHEMA_TYPE_SEQUENCE:
3825             case XML_SCHEMA_TYPE_GROUP:
3826             case XML_SCHEMA_TYPE_ALL:
3827             case XML_SCHEMA_TYPE_CHOICE:
3828                 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3829                 break;
3830             case XML_SCHEMA_TYPE_BASIC:
3831             case XML_SCHEMA_TYPE_ANY:
3832             case XML_SCHEMA_TYPE_FACET:
3833             case XML_SCHEMA_TYPE_SIMPLE:
3834             case XML_SCHEMA_TYPE_UR:
3835             case XML_SCHEMA_TYPE_ELEMENT:
3836             case XML_SCHEMA_TYPE_ATTRIBUTE:
3837             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
3838             case XML_SCHEMA_TYPE_NOTATION:
3839             case XML_SCHEMA_TYPE_LIST:
3840             case XML_SCHEMA_TYPE_UNION:
3841             case XML_SCHEMA_FACET_MININCLUSIVE:
3842             case XML_SCHEMA_FACET_MINEXCLUSIVE:
3843             case XML_SCHEMA_FACET_MAXINCLUSIVE:
3844             case XML_SCHEMA_FACET_MAXEXCLUSIVE:
3845             case XML_SCHEMA_FACET_TOTALDIGITS:
3846             case XML_SCHEMA_FACET_FRACTIONDIGITS:
3847             case XML_SCHEMA_FACET_PATTERN:
3848             case XML_SCHEMA_FACET_ENUMERATION:
3849             case XML_SCHEMA_FACET_WHITESPACE:
3850             case XML_SCHEMA_FACET_LENGTH:
3851             case XML_SCHEMA_FACET_MAXLENGTH:
3852             case XML_SCHEMA_FACET_MINLENGTH:
3853                 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
3854                 break;
3855         }
3856     } 
3857 #ifdef DEBUG_TYPE
3858     if (typeDecl->node != NULL) {
3859         xmlGenericError(xmlGenericErrorContext,
3860                 "Type of %s : %s:%d :", name, typeDecl->node->doc->URL,
3861                         xmlGetLineNo(typeDecl->node));
3862     } else {
3863         xmlGenericError(xmlGenericErrorContext,
3864                 "Type of %s :", name);
3865     }
3866     switch (typeDecl->contentType) {
3867         case XML_SCHEMA_CONTENT_SIMPLE:
3868             xmlGenericError(xmlGenericErrorContext,
3869                     "simple\n"); break;
3870         case XML_SCHEMA_CONTENT_ELEMENTS:
3871             xmlGenericError(xmlGenericErrorContext,
3872                     "elements\n"); break;
3873         case XML_SCHEMA_CONTENT_UNKNOWN:
3874             xmlGenericError(xmlGenericErrorContext,
3875                     "unknown !!!\n"); break;
3876         case XML_SCHEMA_CONTENT_EMPTY:
3877             xmlGenericError(xmlGenericErrorContext,
3878                     "empty\n"); break;
3879         case XML_SCHEMA_CONTENT_MIXED:
3880             xmlGenericError(xmlGenericErrorContext,
3881                     "mixed\n"); break;
3882         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
3883             xmlGenericError(xmlGenericErrorContext,
3884                     "mixed or elems\n"); break;
3885         case XML_SCHEMA_CONTENT_BASIC:
3886             xmlGenericError(xmlGenericErrorContext,
3887                     "basic\n"); break;
3888         default:
3889             xmlGenericError(xmlGenericErrorContext,
3890                     "not registered !!!\n"); break;
3891     }
3892 #endif
3893 }
3894
3895 /**
3896  * xmlSchemaCheckFacet:
3897  * @facet:  the facet
3898  * @typeDecl:  the schema type definition
3899  * @ctxt:  the schema parser context or NULL
3900  * @name: name of the type
3901  *
3902  * Checks the default values types, especially for facets 
3903  *
3904  * Returns 0 if okay or -1 in cae of error
3905  */
3906 int
3907 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
3908                     xmlSchemaTypePtr typeDecl,
3909                     xmlSchemaParserCtxtPtr ctxt,
3910                     const xmlChar *name)
3911 {
3912     static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
3913     int ret = 0;
3914
3915     if (nonNegativeIntegerType == NULL) {
3916         nonNegativeIntegerType = xmlSchemaGetPredefinedType(
3917                 BAD_CAST "nonNegativeInteger", xmlSchemaNs);
3918     }
3919     switch (facet->type) {
3920         case XML_SCHEMA_FACET_MININCLUSIVE:
3921         case XML_SCHEMA_FACET_MINEXCLUSIVE:
3922         case XML_SCHEMA_FACET_MAXINCLUSIVE:
3923         case XML_SCHEMA_FACET_MAXEXCLUSIVE: {
3924             /*
3925              * Okay we need to validate the value
3926              * at that point.
3927              */
3928             xmlSchemaValidCtxtPtr vctxt;
3929
3930             vctxt = xmlSchemaNewValidCtxt(NULL);
3931             if (vctxt == NULL)
3932                 break;
3933             xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3934                                          facet->value);
3935             facet->val = vctxt->value;
3936             vctxt->value = NULL;
3937             if (facet->val == NULL) {
3938                 /* error code */
3939                 if (ctxt != NULL) {
3940                     ctxt->nberrors++;
3941                     xmlSchemaErrorContext(ctxt, NULL,
3942                             facet->node, NULL);
3943                     ctxt->error(ctxt->userData,
3944                     "Schemas: type %s facet value %s invalid\n",
3945                                 name, facet->value);
3946                 }
3947                 ret = -1;
3948             }
3949             xmlSchemaFreeValidCtxt(vctxt);
3950             break;
3951         }
3952         case XML_SCHEMA_FACET_ENUMERATION: {
3953             /*
3954              * Okay we need to validate the value
3955              * at that point.
3956              */
3957             xmlSchemaValidCtxtPtr vctxt;
3958             int tmp;
3959
3960             vctxt = xmlSchemaNewValidCtxt(NULL);
3961             if (vctxt == NULL)
3962                 break;
3963             tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3964                                          facet->value);
3965             if (tmp != 0) {
3966                 if (ctxt != NULL) {
3967                     ctxt->nberrors++;
3968                     xmlSchemaErrorContext(ctxt, NULL,
3969                             facet->node, NULL);
3970                     ctxt->error(ctxt->userData,
3971                     "Schemas: type %s enumeration value %s invalid\n",
3972                                 name, facet->value);
3973                 }
3974                 ret = -1;
3975             }
3976             xmlSchemaFreeValidCtxt(vctxt);
3977             break;
3978         }
3979         case XML_SCHEMA_FACET_PATTERN:
3980             facet->regexp = xmlRegexpCompile(facet->value);
3981             if (facet->regexp == NULL) {
3982                 /* error code */
3983                 if (ctxt != NULL) {
3984                     ctxt->nberrors++;
3985                     ctxt->error(ctxt->userData,
3986                 "Schemas: type %s facet regexp %s invalid\n",
3987                                 name, facet->value);
3988                 }
3989                 ret = -1;
3990             }
3991             break;
3992         case XML_SCHEMA_FACET_TOTALDIGITS:
3993         case XML_SCHEMA_FACET_FRACTIONDIGITS:
3994         case XML_SCHEMA_FACET_LENGTH:
3995         case XML_SCHEMA_FACET_MAXLENGTH:
3996         case XML_SCHEMA_FACET_MINLENGTH: {
3997             int tmp;
3998
3999             tmp = xmlSchemaValidatePredefinedType(
4000                          nonNegativeIntegerType, facet->value,
4001                          &facet->val);
4002             if (tmp != 0) {
4003                 /* error code */
4004                 if (ctxt != NULL) {
4005                     ctxt->nberrors++;
4006                     xmlSchemaErrorContext(ctxt, NULL,
4007                             facet->node, NULL);
4008                     ctxt->error(ctxt->userData,
4009                     "Schemas: type %s facet value %s invalid\n",
4010                                 name, facet->value);
4011                 }
4012                 ret = -1;
4013             }
4014             break;
4015         }
4016         case XML_SCHEMA_FACET_WHITESPACE: {
4017             if (xmlStrEqual(facet->value, BAD_CAST"preserve")) {
4018                 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4019             } else if (xmlStrEqual(facet->value,
4020                         BAD_CAST"replace")) {
4021                 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4022             } else if (xmlStrEqual(facet->value,
4023                         BAD_CAST"collapse")) {
4024                 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4025             } else {
4026                 if (ctxt != NULL) {
4027                     ctxt->nberrors++;
4028                     xmlSchemaErrorContext(ctxt, NULL,
4029                             facet->node, NULL);
4030                     ctxt->error(ctxt->userData,
4031                     "Schemas: type %s whiteSpace value %s invalid\n",
4032                                 name, facet->value);
4033                 }
4034                 ret = -1;
4035             }
4036         }
4037         default:
4038             break;
4039     }
4040     return(ret);
4041 }
4042
4043 /**
4044  * xmlSchemaCheckDefaults:
4045  * @typeDecl:  the schema type definition
4046  * @ctxt:  the schema parser context
4047  *
4048  * Checks the default values types, especially for facets 
4049  */
4050 static void
4051 xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
4052                    xmlSchemaParserCtxtPtr ctxt,
4053                    const xmlChar *name)
4054 {
4055     if (name == NULL)
4056         name = typeDecl->name;
4057     if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
4058         if (typeDecl->facets != NULL) {
4059             xmlSchemaFacetPtr facet = typeDecl->facets;
4060             while (facet != NULL) {
4061                 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4062                 facet = facet->next;
4063             }
4064         }
4065     }
4066 }
4067
4068 /**
4069  * xmlSchemaAttrGrpFixup:
4070  * @attrgrpDecl:  the schema attribute definition
4071  * @ctxt:  the schema parser context
4072  * @name:  the attribute name
4073  *
4074  * Fixes finish doing the computations on the attributes definitions
4075  */
4076 static void
4077 xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
4078                    xmlSchemaParserCtxtPtr ctxt,
4079                    const xmlChar *name)
4080 {
4081     if (name == NULL)
4082         name = attrgrpDecl->name;
4083     if (attrgrpDecl->attributes != NULL)
4084         return;
4085     if (attrgrpDecl->ref != NULL) {
4086         xmlSchemaAttributeGroupPtr ref;
4087
4088         ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4089                              attrgrpDecl->refNs);
4090         if (ref == NULL) {
4091             ctxt->nberrors++;
4092             xmlSchemaErrorContext(ctxt, NULL, attrgrpDecl->node, NULL);
4093             if ((ctxt != NULL) && (ctxt->error != NULL))
4094                 ctxt->error(ctxt->userData,
4095                     "Schemas: attribute group %s reference %s not found\n",
4096                             name, attrgrpDecl->ref);
4097             return;
4098         }
4099         xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4100         attrgrpDecl->attributes = ref->attributes;
4101     } else {
4102         ctxt->nberrors++;
4103         xmlSchemaErrorContext(ctxt, NULL, attrgrpDecl->node, NULL);
4104         if ((ctxt != NULL) && (ctxt->error != NULL))
4105             ctxt->error(ctxt->userData,
4106                 "Schemas: attribute %s has no attributes nor reference\n",
4107                         name);
4108     }
4109 }
4110
4111 /**
4112  * xmlSchemaAttrFixup:
4113  * @attrDecl:  the schema attribute definition
4114  * @ctxt:  the schema parser context
4115  * @name:  the attribute name
4116  *
4117  * Fixes finish doing the computations on the attributes definitions
4118  */
4119 static void
4120 xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
4121                    xmlSchemaParserCtxtPtr ctxt,
4122                    const xmlChar *name)
4123 {
4124     if (name == NULL)
4125         name = attrDecl->name;
4126     if (attrDecl->subtypes != NULL)
4127         return;
4128     if (attrDecl->typeName != NULL) {
4129         xmlSchemaTypePtr type;
4130
4131         type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4132                                     attrDecl->typeNs);
4133         if (type == NULL) {
4134             ctxt->nberrors++;
4135             xmlSchemaErrorContext(ctxt, NULL, attrDecl->node, NULL);
4136             if ((ctxt != NULL) && (ctxt->error != NULL))
4137                 ctxt->error(ctxt->userData,
4138                     "Schemas: attribute %s type %s not found\n",
4139                             name, attrDecl->typeName);
4140         }
4141         attrDecl->subtypes = type;
4142     } else if (attrDecl->ref != NULL) {
4143         xmlSchemaAttributePtr ref;
4144
4145         ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4146                              attrDecl->refNs);
4147         if (ref == NULL) {
4148             ctxt->nberrors++;
4149             xmlSchemaErrorContext(ctxt, NULL, attrDecl->node, NULL);
4150             if ((ctxt != NULL) && (ctxt->error != NULL))
4151                 ctxt->error(ctxt->userData,
4152                     "Schemas: attribute %s reference %s not found\n",
4153                             name, attrDecl->ref);
4154             return;
4155         }
4156         xmlSchemaAttrFixup(ref, ctxt, NULL);
4157         attrDecl->subtypes = ref->subtypes;
4158     } else {
4159         ctxt->nberrors++;
4160         xmlSchemaErrorContext(ctxt, NULL, attrDecl->node, NULL);
4161         if ((ctxt != NULL) && (ctxt->error != NULL))
4162             ctxt->error(ctxt->userData,
4163                 "Schemas: attribute %s has no type nor reference\n",
4164                         name);
4165     }
4166 }
4167
4168 /**
4169  * xmlSchemaParse:
4170  * @ctxt:  a schema validation context
4171  *
4172  * parse a schema definition resource and build an internal
4173  * XML Shema struture which can be used to validate instances.
4174  * *WARNING* this interface is highly subject to change
4175  *
4176  * Returns the internal XML Schema structure built from the resource or
4177  *         NULL in case of error
4178  */
4179 xmlSchemaPtr
4180 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4181 {
4182     xmlSchemaPtr ret = NULL;
4183     xmlDocPtr doc;
4184     xmlNodePtr root, cur, delete;
4185     int nberrors;
4186
4187     xmlSchemaInitTypes();
4188
4189     if (ctxt == NULL)
4190         return (NULL);
4191
4192     nberrors = ctxt->nberrors;
4193     ctxt->nberrors = 0;
4194     ctxt->counter = 0;
4195     ctxt->container = NULL;
4196
4197     /*
4198      * First step is to parse the input document into an DOM/Infoset
4199      */
4200     if (ctxt->URL != NULL) {
4201         doc = xmlParseFile((const char *) ctxt->URL);
4202         if (doc == NULL) {
4203             ctxt->nberrors++;
4204             if (ctxt->error != NULL)
4205                 ctxt->error(ctxt->userData,
4206                             "xmlSchemaParse: could not load %s\n", ctxt->URL);
4207             return (NULL);
4208         }
4209     } else if (ctxt->buffer != NULL) {
4210         doc = xmlParseMemory(ctxt->buffer, ctxt->size);
4211         if (doc == NULL) {
4212             ctxt->nberrors++;
4213             if (ctxt->error != NULL)
4214                 ctxt->error(ctxt->userData,
4215                             "xmlSchemaParse: could not parse schemas\n");
4216             return (NULL);
4217         }
4218         doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
4219         ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
4220     } else {
4221         ctxt->nberrors++;
4222         if (ctxt->error != NULL)
4223             ctxt->error(ctxt->userData,
4224                         "xmlSchemaParse: nothing to parse\n");
4225         return (NULL);
4226     }
4227
4228     /*
4229      * Then extract the root and Schema parse it
4230      */
4231     root = xmlDocGetRootElement(doc);
4232     if (root == NULL) {
4233         ctxt->nberrors++;
4234         if (ctxt->error != NULL)
4235             ctxt->error(ctxt->userData, "xmlSchemaParse: %s is empty\n",
4236                         ctxt->URL);
4237         return (NULL);
4238     }
4239
4240     /*
4241      * Remove all the blank text nodes
4242      */
4243     delete = NULL;
4244     cur = root;
4245     while (cur != NULL) {
4246         if (delete != NULL) {
4247             xmlUnlinkNode(delete);
4248             xmlFreeNode(delete);
4249             delete = NULL;
4250         }
4251         if (cur->type == XML_TEXT_NODE) {
4252             if (IS_BLANK_NODE(cur)) {
4253                 if (xmlNodeGetSpacePreserve(cur) != 1) {
4254                     delete = cur;
4255                 }
4256             }
4257         } else if ((cur->type != XML_ELEMENT_NODE) &&
4258                    (cur->type != XML_CDATA_SECTION_NODE)) {
4259             delete = cur;
4260             goto skip_children;
4261         }
4262
4263         /*
4264          * Skip to next node
4265          */
4266         if (cur->children != NULL) {
4267             if ((cur->children->type != XML_ENTITY_DECL) &&
4268                 (cur->children->type != XML_ENTITY_REF_NODE) &&
4269                 (cur->children->type != XML_ENTITY_NODE)) {
4270                 cur = cur->children;
4271                 continue;
4272             }
4273         }
4274 skip_children:
4275         if (cur->next != NULL) {
4276             cur = cur->next;
4277             continue;
4278         }
4279         
4280         do {
4281             cur = cur->parent;
4282             if (cur == NULL)
4283                 break;
4284             if (cur == root) {
4285                 cur = NULL;
4286                 break;
4287             }
4288             if (cur->next != NULL) {
4289                 cur = cur->next;
4290                 break;
4291             }
4292         } while (cur != NULL);
4293     }
4294     if (delete != NULL) {
4295         xmlUnlinkNode(delete);
4296         xmlFreeNode(delete);
4297         delete = NULL;
4298     }
4299
4300     /*
4301      * Then do the parsing for good
4302      */
4303     ret = xmlSchemaParseSchema(ctxt, root);
4304     if (ret == NULL)
4305         return(NULL);
4306     ret->doc = doc;
4307
4308     /*
4309      * Then fix all the references.
4310      */
4311     ctxt->schema = ret;
4312     xmlHashScanFull(ret->elemDecl,
4313                     (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
4314
4315     /*
4316      * Then fixup all types properties
4317      */
4318     xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4319
4320     /*
4321      * Then build the content model for all elements
4322      */
4323     xmlHashScan(ret->elemDecl,
4324                     (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
4325
4326     /*
4327      * Then check the defaults part of the type like facets values
4328      */
4329     xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt);
4330
4331     /*
4332      * Then fixup all attributes declarations
4333      */
4334     xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4335
4336     /*
4337      * Then fixup all attributes group declarations
4338      */
4339     xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup, ctxt);
4340
4341     if (ctxt->nberrors != 0) {
4342         xmlSchemaFree(ret);
4343         ret = NULL;
4344     }
4345     return (ret);
4346 }
4347  
4348 /**
4349  * xmlSchemaSetParserErrors:
4350  * @ctxt:  a schema validation context
4351  * @err:  the error callback
4352  * @warn:  the warning callback
4353  * @ctx:  contextual data for the callbacks
4354  *
4355  * Set the callback functions used to handle errors for a validation context
4356  */
4357 void
4358 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
4359         xmlSchemaValidityErrorFunc err,
4360         xmlSchemaValidityWarningFunc warn, void *ctx) {
4361     if (ctxt == NULL)
4362         return;
4363     ctxt->error = err;
4364     ctxt->warning = warn;
4365     ctxt->userData = ctx;
4366 }
4367
4368 /**
4369  * xmlSchemaFacetTypeToString:
4370  * @type:  the facet type
4371  *
4372  * Convert the xmlSchemaTypeType to a char string.
4373  *
4374  * Returns the char string representation of the facet type if the
4375  *     type is a facet and an "Internal Error" string otherwise.
4376  */
4377 static const char *
4378 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
4379 {
4380     switch (type) {
4381         case XML_SCHEMA_FACET_PATTERN:
4382             return ("pattern");
4383         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4384             return ("maxExclusive");
4385         case XML_SCHEMA_FACET_MAXINCLUSIVE:
4386             return ("maxInclusive");
4387         case XML_SCHEMA_FACET_MINEXCLUSIVE:
4388             return ("minExclusive");
4389         case XML_SCHEMA_FACET_MININCLUSIVE:
4390             return ("minInclusive");
4391         case XML_SCHEMA_FACET_WHITESPACE:
4392             return ("whiteSpace");
4393         case XML_SCHEMA_FACET_ENUMERATION:
4394             return ("enumeration");
4395         case XML_SCHEMA_FACET_LENGTH:
4396             return ("length");
4397         case XML_SCHEMA_FACET_MAXLENGTH:
4398             return ("maxLength");
4399         case XML_SCHEMA_FACET_MINLENGTH:
4400             return ("minLength");
4401         case XML_SCHEMA_FACET_TOTALDIGITS:
4402             return ("totalDigits");
4403         case XML_SCHEMA_FACET_FRACTIONDIGITS:
4404             return ("fractionDigits");
4405         default:
4406             break;
4407     }
4408     return ("Internal Error");
4409 }
4410
4411 /**
4412  * xmlSchemaValidateFacets:
4413  * @ctxt:  a schema validation context
4414  * @base:  the base type
4415  * @facets:  the list of facets to check
4416  * @value:  the lexical repr of the value to validate
4417  * @val:  the precomputed value
4418  *
4419  * Check a value against all facet conditions
4420  *
4421  * Returns 0 if the element is schemas valid, a positive error code
4422  *     number otherwise and -1 in case of internal or API error.
4423  */
4424 static int
4425 xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt, 
4426                              xmlSchemaTypePtr base,
4427                             xmlSchemaFacetPtr facets,
4428                                      xmlChar *value) {
4429     int ret = 0;
4430     int tmp = 0;
4431     xmlSchemaTypeType type;
4432     xmlSchemaFacetPtr facet = facets;
4433
4434     while (facet != NULL) {
4435         type = facet->type;
4436         if (type == XML_SCHEMA_FACET_ENUMERATION) {
4437             tmp = 1;
4438
4439             while (facet != NULL) {
4440                 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
4441                 if (tmp == 0) {
4442                     return 0;
4443                 }
4444                 facet = facet->next;
4445             }
4446         } else
4447             tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
4448
4449         if (tmp != 0) {
4450             ret = tmp;
4451             ctxt->nberrors++;
4452             if (ctxt->error != NULL)
4453                 ctxt->error(ctxt->userData,
4454                      "Failed to validate type with facet %s\n",
4455                      xmlSchemaFacetTypeToString(type));
4456             ctxt->err = XML_SCHEMAS_ERR_FACET;
4457         }
4458         if (facet != NULL)
4459             facet = facet->next;
4460     }
4461     return (ret);
4462 }
4463
4464 /************************************************************************
4465  *                                                                      *
4466  *                      Simple type validation                          *
4467  *                                                                      *
4468  ************************************************************************/
4469
4470 /**
4471  * xmlSchemaValidateSimpleValue:
4472  * @ctxt:  a schema validation context
4473  * @type:  the type declaration
4474  * @value:  the value to validate
4475  *
4476  * Validate a value against a simple type
4477  *
4478  * Returns 0 if the value is valid, a positive error code
4479  *     number otherwise and -1 in case of internal or API error.
4480  */
4481 static int
4482 xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt, 
4483                              xmlSchemaTypePtr type,
4484                              xmlChar *value) {
4485     int ret = 0;
4486     /*
4487      * First normalize the value accordingly to Schema Datatype
4488      * 4.3.6 whiteSpace definition of the whiteSpace facet of type
4489      */
4490     /*
4491      * Then check the normalized value against the lexical space of the
4492      * type.
4493      */
4494     if (type->type == XML_SCHEMA_TYPE_BASIC) {
4495         if (ctxt->value != NULL) {
4496             xmlSchemaFreeValue(ctxt->value);
4497             ctxt->value = NULL;
4498         }
4499         ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
4500                                          ctxt->cur);
4501         if (ret != 0) {
4502             ctxt->nberrors++;
4503             if (ctxt->error != NULL)
4504                 ctxt->error(ctxt->userData,
4505                         "Failed to validate basic type %s\n", type->name);
4506             ctxt->err = XML_SCHEMAS_ERR_VALUE;
4507         }
4508     } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
4509         xmlSchemaTypePtr base;
4510         xmlSchemaFacetPtr facet;
4511
4512         base = type->baseType;
4513         if (base != NULL) {
4514             ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4515         } else if (type->subtypes != NULL) {
4516             
4517         }
4518         /*
4519          * Do not validate facets when working on building the Schemas
4520          */
4521         if (ctxt->schema != NULL) {
4522             if (ret == 0) {
4523                 facet = type->facets;
4524                 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
4525             }
4526         }
4527     } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
4528         xmlSchemaTypePtr base;
4529
4530         base = type->subtypes;
4531         if (base != NULL) {
4532             ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4533         } else {
4534             TODO
4535         }
4536     } else if (type->type == XML_SCHEMA_TYPE_LIST) {
4537         xmlSchemaTypePtr base;
4538         xmlChar *cur, *end, tmp;
4539         int ret2;
4540
4541         base = type->subtypes;
4542         if (base == NULL) {
4543             ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4544             ctxt->nberrors++;
4545             if (ctxt->error != NULL) {
4546                 xmlSchemaErrorContext(NULL, ctxt->schema, type->node, NULL);
4547                 ctxt->error(ctxt->userData,
4548                 "Internal: List type %s has no base type\n",
4549                             type->name);
4550             }
4551             return(-1);
4552         }
4553         cur = value;
4554         do {
4555             while (IS_BLANK(*cur)) cur++;
4556             end = cur;
4557             while ((*end != 0) && (!(IS_BLANK(*end)))) end++;
4558             if (end == cur)
4559                 break;
4560             tmp = *end;
4561             *end = 0;
4562             ret2 = xmlSchemaValidateSimpleValue(ctxt, base, cur);
4563             if (ret2 != 0)
4564                 ret = 1;
4565             *end = tmp;
4566             cur = end;
4567         } while (*cur != 0);
4568     } else {
4569         TODO
4570     }
4571     return(ret);
4572 }
4573
4574 /************************************************************************
4575  *                                                                      *
4576  *                      DOM Validation code                             *
4577  *                                                                      *
4578  ************************************************************************/
4579
4580 static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
4581                                     xmlNodePtr node);
4582 static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
4583         xmlNodePtr elem, xmlSchemaAttributePtr attributes);
4584 static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
4585         xmlNodePtr elem, xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type);
4586
4587 /**
4588  * xmlSchemaRegisterAttributes:
4589  * @ctxt:  a schema validation context
4590  * @attrs:  a list of attributes
4591  *
4592  * Register the list of attributes as the set to be validated on that element
4593  *
4594  * Returns -1 in case of error, 0 otherwise
4595  */
4596 static int
4597 xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt,
4598                             xmlAttrPtr attrs) {
4599     while (attrs != NULL) {
4600         if ((attrs->ns != NULL) &&
4601             (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
4602             attrs = attrs->next;
4603             continue;
4604         }
4605         if (ctxt->attrNr >= ctxt->attrMax) {
4606             xmlSchemaAttrStatePtr tmp;
4607
4608             ctxt->attrMax *= 2;
4609             tmp = (xmlSchemaAttrStatePtr)
4610                           xmlRealloc(ctxt->attr, ctxt->attrMax *
4611                                      sizeof(xmlSchemaAttrState));
4612             if (tmp == NULL) {
4613                 ctxt->attrMax /= 2;
4614                 return(-1);
4615             }
4616             ctxt->attr = tmp;
4617         }
4618         ctxt->attr[ctxt->attrNr].attr = attrs;
4619         ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
4620         ctxt->attrNr++;
4621         attrs = attrs->next;
4622     }
4623     return(0);
4624 }
4625
4626 /**
4627  * xmlSchemaCheckAttributes:
4628  * @ctxt:  a schema validation context
4629  * @node:  the node carrying it.
4630  *
4631  * Check that the registered set of attributes on the current node
4632  * has been properly validated.
4633  *
4634  * Returns 0 if validity constraints are met, 1 otherwise.
4635  */
4636 static int
4637 xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4638     int ret = 0;
4639     int i;
4640
4641     for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
4642         if (ctxt->attr[i].attr == NULL)
4643             break;
4644         if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
4645             ret = 1;
4646             ctxt->err = XML_SCHEMAS_ERR_ATTRUNKNOWN;
4647             ctxt->nberrors++;
4648             if (ctxt->error != NULL)
4649                 ctxt->error(ctxt->userData,
4650                 "Attribute %s on %s is unknown\n",
4651                             ctxt->attr[i].attr->name,
4652                             node->name);
4653         }
4654     }
4655     return(ret);
4656 }
4657
4658 /**
4659  * xmlSchemaValidateSimpleContent:
4660  * @ctxt:  a schema validation context
4661  * @elem:  an element
4662  * @type:  the type declaration
4663  *
4664  * Validate the content of an element expected to be a simple type
4665  *
4666  * Returns 0 if the element is schemas valid, a positive error code
4667  *     number otherwise and -1 in case of internal or API error.
4668  */
4669 static int
4670 xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
4671                                xmlNodePtr node ATTRIBUTE_UNUSED) {
4672     xmlNodePtr child;
4673     xmlSchemaTypePtr type, base;
4674     xmlChar *value;
4675     int ret = 0;
4676
4677     child = ctxt->node;
4678     type = ctxt->type;
4679
4680     /*
4681      * Validation Rule: Element Locally Valid (Type): 3.1.3
4682      */
4683     value = xmlNodeGetContent(child);
4684     /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
4685     switch (type->type) {
4686         case XML_SCHEMA_TYPE_RESTRICTION: {
4687             xmlSchemaFacetPtr facet;
4688
4689             base = type->baseType;
4690             if (base != NULL) {
4691                 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4692             } else {
4693                 TODO
4694             }
4695             if (ret == 0) {
4696                 facet = type->facets;
4697                 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
4698             }
4699             break;
4700         }
4701         default:
4702             TODO
4703     }
4704     if (value != NULL)
4705         xmlFree(value);
4706
4707     return(ret);
4708 }
4709
4710 /**
4711  * xmlSchemaValidateCheckNodeList
4712  * @nodelist: the list of nodes
4713  *
4714  * Check the node list is only made of text nodes and entities pointing
4715  * to text nodes
4716  *
4717  * Returns 1 if true, 0 if false and -1 in case of error
4718  */
4719 static int
4720 xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist) {
4721     while (nodelist != NULL) {
4722         if (nodelist->type == XML_ENTITY_REF_NODE) {
4723             TODO /* implement recursion in the entity content */
4724         }
4725         if ((nodelist->type != XML_TEXT_NODE) &&
4726             (nodelist->type != XML_COMMENT_NODE) &&
4727             (nodelist->type != XML_PI_NODE) &&
4728             (nodelist->type != XML_PI_NODE)) {
4729             return(0);
4730         }
4731         nodelist = nodelist->next;
4732     }
4733     return(1);
4734 }
4735
4736 /**
4737  * xmlSchemaSkipIgnored:
4738  * @ctxt:  a schema validation context
4739  * @type:  the current type context
4740  * @node:  the top node.
4741  *
4742  * Skip ignorable nodes in that context
4743  *
4744  * Returns the new sibling
4745  *     number otherwise and -1 in case of internal or API error.
4746  */
4747 static xmlNodePtr
4748 xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
4749                      xmlSchemaTypePtr type,
4750                      xmlNodePtr node) {
4751     int mixed = 0;
4752     /*
4753      * TODO complete and handle entities
4754      */
4755     mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
4756              (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
4757     while ((node != NULL) &&
4758            ((node->type == XML_COMMENT_NODE) ||
4759             ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
4760             (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
4761              (node->type == XML_TEXT_NODE) &&
4762              (IS_BLANK_NODE(node)))))) {
4763         node = node->next;
4764     }
4765     return(node);
4766 }
4767
4768 /**
4769  * xmlSchemaValidateCallback:
4770  * @ctxt:  a schema validation context
4771  * @name:  the name of the element detected (might be NULL)
4772  * @type:  the type
4773  *
4774  * A transition has been made in the automata associated to an element
4775  * content model
4776  */
4777 static void
4778 xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
4779                           const xmlChar *name ATTRIBUTE_UNUSED,
4780                           xmlSchemaTypePtr type,
4781                           xmlNodePtr node) {
4782     xmlSchemaTypePtr oldtype = ctxt->type;
4783     xmlNodePtr oldnode = ctxt->node;
4784 #ifdef DEBUG_CONTENT
4785     xmlGenericError(xmlGenericErrorContext,
4786                     "xmlSchemaValidateCallback: %s, %s, %s\n",
4787                     name, type->name, node->name);
4788 #endif
4789     ctxt->type = type;
4790     ctxt->node = node;
4791     xmlSchemaValidateContent(ctxt, node);
4792     ctxt->type = oldtype;
4793     ctxt->node = oldnode;
4794 }
4795
4796
4797 #if 0
4798 /**
4799  * xmlSchemaValidateSimpleRestrictionType:
4800  * @ctxt:  a schema validation context
4801  * @node:  the top node.
4802  *
4803  * Validate the content of a restriction type.
4804  *
4805  * Returns 0 if the element is schemas valid, a positive error code
4806  *     number otherwise and -1 in case of internal or API error.
4807  */
4808 static int
4809 xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
4810                                        xmlNodePtr node)
4811 {
4812     xmlNodePtr child;
4813     xmlSchemaTypePtr type;
4814     int ret;
4815
4816     child = ctxt->node;
4817     type = ctxt->type;
4818
4819     if ((ctxt == NULL) || (type == NULL)) {
4820         ctxt->nberrors++;
4821         ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4822         if (ctxt->error != NULL)
4823             ctxt->error(ctxt->userData,
4824             "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
4825                         node->name);
4826         return (-1);
4827     }
4828     /*
4829      * Only text and text based entities references shall be found there
4830      */
4831     ret = xmlSchemaValidateCheckNodeList(child);
4832     if (ret < 0) {
4833         ctxt->nberrors++;
4834         ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4835         if (ctxt->error != NULL)
4836             ctxt->error(ctxt->userData,
4837                 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4838                         node->name);
4839         return (-1);
4840     } else if (ret == 0) {
4841         ctxt->nberrors++;
4842         ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4843         if (ctxt->error != NULL)
4844             ctxt->error(ctxt->userData,
4845                         "Element %s content is not a simple type\n",
4846                         node->name);
4847         return (-1);
4848     }
4849     ctxt->type = type->subtypes;
4850     xmlSchemaValidateContent(ctxt, node);
4851     ctxt->type = type;
4852     return (ret);
4853 }
4854 #endif
4855
4856 /**
4857  * xmlSchemaValidateSimpleType:
4858  * @ctxt:  a schema validation context
4859  * @node:  the top node.
4860  *
4861  * Validate the content of an simple type.
4862  *
4863  * Returns 0 if the element is schemas valid, a positive error code
4864  *     number otherwise and -1 in case of internal or API error.
4865  */
4866 static int
4867 xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4868     xmlNodePtr child;
4869     xmlSchemaTypePtr type;
4870     xmlAttrPtr attr;
4871     int ret;
4872
4873     child = ctxt->node;
4874     type = ctxt->type;
4875
4876     if ((ctxt == NULL) || (type == NULL)) {
4877         ctxt->nberrors++;
4878         ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4879         if (ctxt->error != NULL)
4880             ctxt->error(ctxt->userData,
4881                     "Internal error: xmlSchemaValidateSimpleType %s\n",
4882                         node->name);
4883         return(-1);
4884     }
4885     /*
4886      * Only text and text based entities references shall be found there
4887      */
4888     ret = xmlSchemaValidateCheckNodeList(child);
4889     if (ret < 0) {
4890         ctxt->nberrors++;
4891         ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4892         if (ctxt->error != NULL)
4893             ctxt->error(ctxt->userData,
4894                     "Internal error: xmlSchemaValidateSimpleType %s content\n",
4895                         node->name);
4896         return(-1);
4897     } else if (ret == 0) {
4898         ctxt->nberrors++;
4899         ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4900         if (ctxt->error != NULL)
4901             ctxt->error(ctxt->userData,
4902                     "Element %s content is not a simple type\n",
4903                         node->name);
4904         return(-1);
4905     }
4906     /*
4907      * Validation Rule: Element Locally Valid (Type): 3.1.1
4908      */
4909     attr = node->properties;
4910     while (attr != NULL) {
4911         if ((attr->ns == NULL) ||
4912             (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
4913             ((!xmlStrEqual(attr->name, BAD_CAST"type")) &&
4914              (!xmlStrEqual(attr->name, BAD_CAST"nil")) &&
4915              (!xmlStrEqual(attr->name, BAD_CAST"schemasLocation")) &&
4916              (!xmlStrEqual(attr->name, BAD_CAST"noNamespaceSchemaLocation")))) {
4917             ctxt->err = XML_SCHEMAS_ERR_INVALIDATTR;
4918             ctxt->nberrors++;
4919             if (ctxt->error != NULL)
4920                 ctxt->error(ctxt->userData,
4921                         "Element %s: attribute %s should not be present\n",
4922                             node->name, attr->name);
4923             return(ctxt->err);
4924         }
4925     }
4926
4927     ctxt->type = type->subtypes;
4928     ret = xmlSchemaValidateSimpleContent(ctxt, node);
4929     ctxt->type = type;
4930     return(ret);
4931 }
4932
4933 /**
4934  * xmlSchemaValidateElementType:
4935  * @ctxt:  a schema validation context
4936  * @node:  the top node.
4937  *
4938  * Validate the content of an element type.
4939  * Validation Rule: Element Locally Valid (Complex Type)
4940  *
4941  * Returns 0 if the element is schemas valid, a positive error code
4942  *     number otherwise and -1 in case of internal or API error.
4943  */
4944 static int
4945 xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4946     xmlNodePtr child;
4947     xmlSchemaTypePtr type;
4948     xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
4949     xmlSchemaElementPtr decl;
4950     int ret, attrBase;
4951
4952     oldregexp = ctxt->regexp;
4953
4954     child = ctxt->node;
4955     type = ctxt->type;
4956
4957     if ((ctxt == NULL) || (type == NULL)) {
4958         ctxt->nberrors++;
4959         ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4960         if (ctxt->error != NULL)
4961             ctxt->error(ctxt->userData,
4962                     "Internal error: xmlSchemaValidateElementType\n",
4963                         node->name);
4964         return(-1);
4965     }
4966     if (child == NULL) {
4967         if (type->minOccurs > 0) {
4968             ctxt->nberrors++;
4969             ctxt->err = XML_SCHEMAS_ERR_MISSING;
4970             if (ctxt->error != NULL)
4971                 ctxt->error(ctxt->userData,
4972                         "Element %s: missing child %s\n",
4973                             node->name, type->name);
4974         }
4975         return(ctxt->err);
4976     }
4977
4978     /*
4979      * Verify the element matches
4980      */
4981     if (!xmlStrEqual(child->name, type->name)) {
4982         ctxt->nberrors++;
4983         ctxt->err = XML_SCHEMAS_ERR_WRONGELEM;
4984         if (ctxt->error != NULL)
4985             ctxt->error(ctxt->userData,
4986                     "Element %s: missing child %s found %s\n",
4987                         node->name, type->name, child->name);
4988         return(ctxt->err);
4989     }
4990     /*
4991      * Verify the attributes
4992      */
4993     attrBase = ctxt->attrBase;
4994     ctxt->attrBase = ctxt->attrNr;
4995     xmlSchemaRegisterAttributes(ctxt, child->properties);
4996     xmlSchemaValidateAttributes(ctxt, child, type->attributes);
4997     /*
4998      * Verify the element content recursively
4999      */
5000     decl = (xmlSchemaElementPtr) type;
5001     oldregexp = ctxt->regexp;
5002     if (decl->contModel != NULL) {
5003         ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5004                              (xmlRegExecCallbacks) xmlSchemaValidateCallback,
5005                              ctxt);
5006 #ifdef DEBUG_AUTOMATA
5007         xmlGenericError(xmlGenericErrorContext,
5008                 "====> %s\n", node->name);
5009 #endif
5010     }
5011     xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr)type,
5012                           type->subtypes);
5013
5014     if (decl->contModel != NULL) {
5015         ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
5016 #ifdef DEBUG_AUTOMATA
5017         xmlGenericError(xmlGenericErrorContext,
5018                 "====> %s : %d\n", node->name, ret);
5019 #endif
5020         if (ret == 0) {
5021             ctxt->nberrors++;
5022             ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
5023             if (ctxt->error != NULL)
5024                 ctxt->error(ctxt->userData, "Element %s content check failed\n",
5025                             node->name);
5026         } else if (ret < 0) {
5027             ctxt->nberrors++;
5028             ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
5029             if (ctxt->error != NULL)
5030                 ctxt->error(ctxt->userData, "Element %s content check failure\n",
5031                             node->name);
5032 #ifdef DEBUG_CONTENT
5033         } else {
5034             xmlGenericError(xmlGenericErrorContext,
5035                             "Element %s content check succeeded\n", node->name);
5036
5037 #endif
5038         }
5039         xmlRegFreeExecCtxt(ctxt->regexp);
5040     }
5041     /*
5042      * Verify that all attributes were Schemas-validated
5043      */
5044     xmlSchemaCheckAttributes(ctxt, node);
5045     ctxt->attrNr = ctxt->attrBase;
5046     ctxt->attrBase = attrBase;
5047
5048     ctxt->regexp = oldregexp;
5049
5050     ctxt->node = child;
5051     ctxt->type = type;
5052     return(ctxt->err);
5053 }
5054
5055 /**
5056  * xmlSchemaValidateBasicType:
5057  * @ctxt:  a schema validation context
5058  * @node:  the top node.
5059  *
5060  * Validate the content of an element expected to be a basic type type
5061  *
5062  * Returns 0 if the element is schemas valid, a positive error code
5063  *     number otherwise and -1 in case of internal or API error.
5064  */
5065 static int
5066 xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
5067     int ret;
5068     xmlNodePtr child, cur;
5069     xmlSchemaTypePtr type;
5070     xmlChar *value;     /* lexical representation */
5071
5072     child = ctxt->node;
5073     type = ctxt->type;
5074
5075     if ((ctxt == NULL) || (type == NULL)) {
5076         ctxt->nberrors++;
5077         ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
5078         if (ctxt->error != NULL)
5079             ctxt->error(ctxt->userData,
5080                     "Internal error: xmlSchemaValidateBasicType\n",
5081                         node->name);
5082         return(-1);
5083     }
5084     /*
5085      * First check the content model of the node.
5086      */
5087     cur = child;
5088     while (cur != NULL) {
5089         switch (cur->type) {
5090             case XML_TEXT_NODE:
5091             case XML_CDATA_SECTION_NODE:
5092             case XML_PI_NODE:
5093             case XML_COMMENT_NODE:
5094             case XML_XINCLUDE_START:
5095             case XML_XINCLUDE_END:
5096                 break;
5097             case XML_ENTITY_REF_NODE:
5098             case XML_ENTITY_NODE:
5099                 TODO
5100                 break;
5101             case XML_ELEMENT_NODE:
5102                 ctxt->nberrors++;
5103                 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
5104                 if (ctxt->error != NULL)
5105                     ctxt->error(ctxt->userData,
5106                             "Element %s: child %s should not be present\n",
5107                                 node->name, cur->name);
5108                 return(ctxt->err);
5109             case XML_ATTRIBUTE_NODE:
5110             case XML_DOCUMENT_NODE:
5111             case XML_DOCUMENT_TYPE_NODE:
5112             case XML_DOCUMENT_FRAG_NODE:
5113             case XML_NOTATION_NODE:
5114             case XML_HTML_DOCUMENT_NODE:
5115             case XML_DTD_NODE:
5116             case XML_ELEMENT_DECL:
5117             case XML_ATTRIBUTE_DECL:
5118             case XML_ENTITY_DECL:
5119             case XML_NAMESPACE_DECL:
5120 #ifdef LIBXML_DOCB_ENABLED
5121             case XML_DOCB_DOCUMENT_NODE:
5122 #endif
5123                 ctxt->nberrors++;
5124                 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
5125                 if (ctxt->error != NULL)
5126                     ctxt->error(ctxt->userData,
5127                             "Element %s: node type %d unexpected here\n",
5128                                 node->name, cur->type);
5129                 return(ctxt->err);
5130         }
5131         cur = cur->next;
5132     }
5133     if (child == NULL)
5134         value = NULL;
5135     else
5136         value = xmlNodeGetContent(child->parent);
5137
5138     if (ctxt->value != NULL) {
5139         xmlSchemaFreeValue(ctxt->value);
5140         ctxt->value = NULL;
5141     }
5142     ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5143     if (value != NULL)
5144         xmlFree(value);
5145     if (ret != 0) {
5146         ctxt->nberrors++;
5147         if (ctxt->error != NULL)
5148             ctxt->error(ctxt->userData,
5149                     "Element %s: failed to validate basic type %s\n",
5150                         node->name, type->name);
5151         ctxt->err = XML_SCHEMAS_ERR_VALUE;
5152     }
5153     return(ret);
5154 }
5155
5156 /**
5157  * xmlSchemaValidateComplexType:
5158  * @ctxt:  a schema validation context
5159  * @node:  the top node.
5160  *
5161  * Validate the content of an element expected to be a complex type type
5162  * xmlschema-1.html#cvc-complex-type
5163  * Validation Rule: Element Locally Valid (Complex Type)
5164  *
5165  * Returns 0 if the element is schemas valid, a positive error code
5166  *     number otherwise and -1 in case of internal or API error.
5167  */
5168 static int
5169 xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
5170     xmlNodePtr child;
5171     xmlSchemaTypePtr type, subtype;
5172     int ret;
5173
5174     child = ctxt->node;
5175     type = ctxt->type;
5176     ctxt->cur = node;
5177
5178     switch (type->contentType) {
5179         case XML_SCHEMA_CONTENT_EMPTY:
5180             if (child != NULL) {
5181                 ctxt->nberrors++;
5182                 if (ctxt->error != NULL)
5183                     ctxt->error(ctxt->userData,
5184                             "Element %s is supposed to be empty\n",
5185                                 node->name);
5186             }
5187             if (type->attributes != NULL) {
5188                 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5189             }
5190             subtype = type->subtypes;
5191             while (subtype != NULL) {
5192                 ctxt->type = subtype;
5193                 xmlSchemaValidateComplexType(ctxt, node);
5194                 subtype = subtype->next;
5195             }
5196             break;
5197         case XML_SCHEMA_CONTENT_ELEMENTS:
5198         case XML_SCHEMA_CONTENT_MIXED:
5199         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5200             /*
5201              * Skip ignorable nodes in that context
5202              */
5203             child = xmlSchemaSkipIgnored(ctxt, type, child);
5204             while (child != NULL) {
5205                 if (child->type == XML_ELEMENT_NODE) {
5206                     ret = xmlRegExecPushString(ctxt->regexp,
5207                                                child->name, child);
5208 #ifdef DEBUG_AUTOMATA
5209                     if (ret < 0)
5210                         xmlGenericError(xmlGenericErrorContext,
5211                                 "  --> %s Error\n", child->name);
5212                     else
5213                         xmlGenericError(xmlGenericErrorContext,
5214                                 "  --> %s\n", child->name);
5215 #endif
5216                 }
5217                 child = child->next;
5218                 /*
5219                  * Skip ignorable nodes in that context
5220                  */
5221                 child = xmlSchemaSkipIgnored(ctxt, type, child);
5222             }
5223             break;
5224         case XML_SCHEMA_CONTENT_BASIC: {
5225             if (type->subtypes != NULL) {
5226                 ctxt->type = type->subtypes;
5227                 xmlSchemaValidateComplexType(ctxt, node);
5228             }
5229             if (type->baseType != NULL) {
5230                 ctxt->type = type->baseType;
5231                 xmlSchemaValidateBasicType(ctxt, node);
5232             }
5233             if (type->attributes != NULL) {
5234                 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5235             }
5236             ctxt->type = type;
5237             break;
5238         }
5239         default:
5240             TODO
5241             xmlGenericError(xmlGenericErrorContext,
5242                     "unimplemented content type %d\n",
5243                             type->contentType);
5244     }
5245     return(ctxt->err);
5246 }
5247
5248 /**
5249  * xmlSchemaValidateContent:
5250  * @ctxt:  a schema validation context
5251  * @elem:  an element
5252  * @type:  the type declaration
5253  *
5254  * Validate the content of an element against the type.
5255  *
5256  * Returns 0 if the element is schemas valid, a positive error code
5257  *     number otherwise and -1 in case of internal or API error.
5258  */
5259 static int
5260 xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
5261     xmlNodePtr child;
5262     xmlSchemaTypePtr type;
5263
5264     child = ctxt->node;
5265     type = ctxt->type;
5266     ctxt->cur = node;
5267
5268     xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5269     ctxt->cur = node;
5270
5271     switch (type->type) {
5272         case XML_SCHEMA_TYPE_ANY:
5273             /* Any type will do it, fine */
5274             TODO /* handle recursivity */
5275             break;
5276         case XML_SCHEMA_TYPE_COMPLEX:
5277             xmlSchemaValidateComplexType(ctxt, node);
5278             break;
5279         case XML_SCHEMA_TYPE_ELEMENT: {
5280             xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5281             /*
5282              * Handle element reference here
5283              */
5284             if (decl->ref != NULL) {
5285                 if (decl->refDecl == NULL) {
5286                     ctxt->nberrors++;
5287                     ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
5288                     if (ctxt->error != NULL)
5289                         ctxt->error(ctxt->userData,
5290                     "Internal error: element reference %s not resolved\n",
5291                                     decl->ref);
5292                     return(-1);
5293                 }
5294                 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5295                 decl = decl->refDecl;
5296             }
5297             xmlSchemaValidateElementType(ctxt, node);
5298             ctxt->type = type;
5299             break;
5300         }
5301         case XML_SCHEMA_TYPE_BASIC:
5302             xmlSchemaValidateBasicType(ctxt, node);
5303             break;
5304         case XML_SCHEMA_TYPE_FACET:
5305             TODO
5306             break;
5307         case XML_SCHEMA_TYPE_SIMPLE:
5308             xmlSchemaValidateSimpleType(ctxt, node);
5309             break;
5310         case XML_SCHEMA_TYPE_SEQUENCE:
5311             TODO
5312             break;
5313         case XML_SCHEMA_TYPE_CHOICE:
5314             TODO
5315             break;
5316         case XML_SCHEMA_TYPE_ALL:
5317             TODO
5318             break;
5319         case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5320             TODO
5321             break;
5322         case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5323             TODO
5324             break;
5325         case XML_SCHEMA_TYPE_UR:
5326             TODO
5327             break;
5328         case XML_SCHEMA_TYPE_RESTRICTION:
5329             /*xmlSchemaValidateRestrictionType(ctxt, node); */
5330             TODO
5331             break;
5332         case XML_SCHEMA_TYPE_EXTENSION:
5333             TODO
5334             break;
5335         case XML_SCHEMA_TYPE_ATTRIBUTE:
5336             TODO
5337             break;
5338         case XML_SCHEMA_TYPE_GROUP:
5339             TODO
5340             break;
5341         case XML_SCHEMA_TYPE_NOTATION:
5342             TODO
5343             break;
5344         case XML_SCHEMA_TYPE_LIST:
5345             TODO
5346             break;
5347         case XML_SCHEMA_TYPE_UNION:
5348             TODO
5349             break;
5350         case XML_SCHEMA_FACET_MININCLUSIVE:
5351             TODO
5352             break;
5353         case XML_SCHEMA_FACET_MINEXCLUSIVE:
5354             TODO
5355             break;
5356         case XML_SCHEMA_FACET_MAXINCLUSIVE:
5357             TODO
5358             break;
5359         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5360             TODO
5361             break;
5362         case XML_SCHEMA_FACET_TOTALDIGITS:
5363             TODO
5364             break;
5365         case XML_SCHEMA_FACET_FRACTIONDIGITS:
5366             TODO
5367             break;
5368         case XML_SCHEMA_FACET_PATTERN:
5369             TODO
5370             break;
5371         case XML_SCHEMA_FACET_ENUMERATION:
5372             TODO
5373             break;
5374         case XML_SCHEMA_FACET_WHITESPACE:
5375             TODO
5376             break;
5377         case XML_SCHEMA_FACET_LENGTH:
5378             TODO
5379             break;
5380         case XML_SCHEMA_FACET_MAXLENGTH:
5381             TODO
5382             break;
5383         case XML_SCHEMA_FACET_MINLENGTH:
5384             TODO
5385             break;
5386         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5387             TODO
5388             break;
5389     }
5390     xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5391
5392     if (ctxt->node == NULL)
5393         return(ctxt->err);
5394     ctxt->node = ctxt->node->next;
5395     ctxt->type = type->next;
5396     return(ctxt->err);
5397 }
5398
5399 /**
5400  * xmlSchemaValidateType:
5401  * @ctxt:  a schema validation context
5402  * @elem:  an element
5403  * @type:  the list of type declarations
5404  *
5405  * Validate the content of an element against the types.
5406  *
5407  * Returns 0 if the element is schemas valid, a positive error code
5408  *     number otherwise and -1 in case of internal or API error.
5409  */
5410 static int
5411 xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
5412                           xmlSchemaElementPtr elemDecl,
5413                           xmlSchemaTypePtr type) {
5414     xmlChar *nil;
5415
5416     if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
5417         return(0);
5418
5419     /*
5420      * 3.3.4 : 2
5421      */
5422     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
5423         ctxt->nberrors++;
5424         ctxt->err = XML_SCHEMAS_ERR_ISABSTRACT;
5425         if (ctxt->error != NULL)
5426             ctxt->error(ctxt->userData, "Element %s is abstract\n", elem->name);
5427         return(ctxt->err);
5428     }
5429     /*
5430      * 3.3.4: 3
5431      */
5432     nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5433     if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
5434         /* 3.3.4: 3.2 */
5435         if (xmlStrEqual(nil, BAD_CAST "true")) {
5436             if (elem->children != NULL) {
5437                 ctxt->nberrors++;
5438                 ctxt->err = XML_SCHEMAS_ERR_NOTEMPTY;
5439                 if (ctxt->error != NULL)
5440                     ctxt->error(ctxt->userData, "Element %s is not empty\n",
5441                                 elem->name);
5442                 return(ctxt->err);
5443             }
5444             if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
5445                 (elemDecl->value != NULL)) {
5446                 ctxt->nberrors++;
5447                 ctxt->err = XML_SCHEMAS_ERR_HAVEDEFAULT;
5448                 if (ctxt->error != NULL)
5449                     ctxt->error(ctxt->userData,
5450                             "Empty element %s cannot get a fixed value\n",
5451                                 elem->name);
5452                 return(ctxt->err);
5453             }
5454         }
5455     } else {
5456         /* 3.3.4: 3.1 */
5457         if (nil != NULL) {
5458             ctxt->err = XML_SCHEMAS_ERR_NOTNILLABLE;
5459             ctxt->nberrors++;
5460             if (ctxt->error != NULL)
5461                 ctxt->error(ctxt->userData,
5462                         "Element %s with xs:nil but not nillable\n",
5463                             elem->name);
5464             xmlFree(nil);
5465             return(ctxt->err);
5466         }
5467     }
5468
5469     /* TODO 3.3.4: 4 if the element carries xs:type*/
5470
5471     ctxt->type = elemDecl->subtypes;
5472     ctxt->node = elem->children;
5473     xmlSchemaValidateContent(ctxt, elem);
5474     xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5475     
5476     return(ctxt->err);
5477 }
5478
5479
5480 /**
5481  * xmlSchemaValidateAttributes:
5482  * @ctxt:  a schema validation context
5483  * @elem:  an element
5484  * @attributes:  the list of attribute declarations
5485  *
5486  * Validate the attributes of an element.
5487  *
5488  * Returns 0 if the element is schemas valid, a positive error code
5489  *     number otherwise and -1 in case of internal or API error.
5490  */
5491 static int
5492 xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
5493                             xmlSchemaAttributePtr attributes) {
5494     int i, ret;
5495     xmlAttrPtr attr;
5496     xmlChar *value;
5497     xmlSchemaAttributeGroupPtr group = NULL;
5498
5499     if (attributes == NULL)
5500         return(0);
5501     while (attributes != NULL) {
5502         /*
5503          * Handle attribute groups
5504          */
5505         if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5506             group = (xmlSchemaAttributeGroupPtr) attributes;
5507             xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
5508             attributes = group->next;
5509             continue;
5510         }
5511         for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
5512             attr = ctxt->attr[i].attr;
5513             if (attr == NULL)
5514                 continue;
5515             if (attributes->ref != NULL) {
5516                 if (!xmlStrEqual(attr->name, attributes->ref))
5517                     continue;
5518                 if (attr->ns != NULL) {
5519                     if ((attributes->refNs == NULL) ||
5520                         (!xmlStrEqual(attr->ns->href, attributes->refNs)))
5521                         continue;
5522                 } else if (attributes->refNs != NULL) {
5523                     continue;
5524                 }
5525             } else {
5526                 if (!xmlStrEqual(attr->name, attributes->name))
5527                     continue;
5528                 /*
5529                  * TODO: handle the mess about namespaces here.
5530                  */
5531                 if ((attr->ns != NULL) /* || (attributes->ns != NULL) */) {
5532                     TODO
5533                 }
5534             }
5535             ctxt->cur = (xmlNodePtr) attributes;
5536             if (attributes->subtypes == NULL) {
5537                 ctxt->nberrors++;
5538                 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
5539                 if (ctxt->error != NULL)
5540                     ctxt->error(ctxt->userData,
5541                 "Internal error: attribute %s type not resolved\n",
5542                                 attr->name);
5543                 continue;
5544             }
5545             value = xmlNodeListGetString(elem->doc, attr->children, 1);
5546             ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
5547                                                value);
5548             if (ret != 0) {
5549                 ctxt->nberrors++;
5550                 ctxt->err = XML_SCHEMAS_ERR_ATTRINVALID;
5551                 if (ctxt->error != NULL)
5552                     ctxt->error(ctxt->userData,
5553                 "attribute %s on %s does not match type\n",
5554                                 attr->name, elem->name);
5555             } else {
5556                 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
5557             }
5558             if (value != NULL) {
5559                 xmlFree(value);
5560             }
5561         }
5562         attributes = attributes->next;
5563     }
5564     return(ctxt->err);
5565 }
5566
5567 /**
5568  * xmlSchemaValidateElement:
5569  * @ctxt:  a schema validation context
5570  * @elem:  an element
5571  *
5572  * Validate an element in a tree
5573  *
5574  * Returns 0 if the element is schemas valid, a positive error code
5575  *     number otherwise and -1 in case of internal or API error.
5576  */
5577 static int
5578 xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem) {
5579     xmlSchemaElementPtr elemDecl;
5580     int ret, attrBase;
5581
5582     if (elem->ns != NULL)
5583         elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5584                 elem->name, elem->ns->href, NULL);
5585     else
5586         elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5587                 elem->name, NULL, NULL);
5588     /*
5589      * 3.3.4 : 1
5590      */
5591     if (elemDecl == NULL) {
5592         ctxt->nberrors++;
5593         ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
5594         if (ctxt->error != NULL)
5595             ctxt->error(ctxt->userData, "Element %s not declared\n",
5596                         elem->name);
5597         return(ctxt->err);
5598     }
5599     if (elemDecl->subtypes == NULL) {
5600         ctxt->nberrors++;
5601         ctxt->err = XML_SCHEMAS_ERR_NOTYPE;
5602         if (ctxt->error != NULL)
5603             ctxt->error(ctxt->userData, "Element %s has no type\n",
5604                         elem->name);
5605         return(ctxt->err);
5606     }
5607     /*
5608      * Verify the attributes
5609      */
5610     attrBase = ctxt->attrBase;
5611     ctxt->attrBase = ctxt->attrNr;
5612     xmlSchemaRegisterAttributes(ctxt, elem->properties);
5613     xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5614     /*
5615      * Verify the element content recursively
5616      */
5617     if (elemDecl->contModel != NULL) {
5618         ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
5619                              (xmlRegExecCallbacks) xmlSchemaValidateCallback,
5620                              ctxt);
5621 #ifdef DEBUG_AUTOMATA
5622         xmlGenericError(xmlGenericErrorContext,
5623                 "====> %s\n", elem->name);
5624 #endif
5625     }
5626     xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
5627     if (elemDecl->contModel != NULL) {
5628         ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
5629 #ifdef DEBUG_AUTOMATA
5630         xmlGenericError(xmlGenericErrorContext,
5631                 "====> %s : %d\n", elem->name, ret);
5632 #endif
5633         if (ret == 0) {
5634             ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
5635             ctxt->nberrors++;
5636             if (ctxt->error != NULL)
5637                 ctxt->error(ctxt->userData, "Element %s content check failed\n",
5638                             elem->name);
5639         } else if (ret < 0) {
5640             ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
5641             ctxt->nberrors++;
5642             if (ctxt->error != NULL)
5643                 ctxt->error(ctxt->userData, "Element %s content check failed\n",
5644                             elem->name);
5645 #ifdef DEBUG_CONTENT
5646         } else {
5647             xmlGenericError(xmlGenericErrorContext,
5648                             "Element %s content check succeeded\n", elem->name);
5649
5650 #endif
5651         }
5652         xmlRegFreeExecCtxt(ctxt->regexp);
5653     }
5654     /*
5655      * Verify that all attributes were Schemas-validated
5656      */
5657     xmlSchemaCheckAttributes(ctxt, elem);
5658     ctxt->attrNr = ctxt->attrBase;
5659     ctxt->attrBase = attrBase;
5660     
5661     return(ctxt->err);
5662 }
5663
5664 /**
5665  * xmlSchemaValidateDocument:
5666  * @ctxt:  a schema validation context
5667  * @doc:  a parsed document tree
5668  *
5669  * Validate a document tree in memory.
5670  *
5671  * Returns 0 if the document is schemas valid, a positive error code
5672  *     number otherwise and -1 in case of internal or API error.
5673  */
5674 static int
5675 xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5676     xmlNodePtr root;
5677     xmlSchemaElementPtr elemDecl;
5678
5679     root = xmlDocGetRootElement(doc);
5680     if (root == NULL) {
5681         ctxt->err = XML_SCHEMAS_ERR_NOROOT;
5682         ctxt->nberrors++;
5683         if (ctxt->error != NULL)
5684             ctxt->error(ctxt->userData, "document has no root\n");
5685         return(ctxt->err);
5686     }
5687     if (root->ns != NULL)
5688         elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5689                 root->name, root->ns->href, NULL);
5690     else
5691         elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5692                 root->name, NULL, NULL);
5693     if (elemDecl == NULL) {
5694         ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
5695         ctxt->nberrors++;
5696         if (ctxt->error != NULL)
5697             ctxt->error(ctxt->userData, "Element %s not declared\n",
5698                         root->name);
5699     } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
5700         ctxt->err = XML_SCHEMAS_ERR_NOTTOPLEVEL;
5701         ctxt->nberrors++;
5702         if (ctxt->error != NULL)
5703             ctxt->error(ctxt->userData, "Root element %s not toplevel\n",
5704                         root->name);
5705     }
5706     /*
5707      * Okay, start the recursive validation
5708      */
5709     xmlSchemaValidateElement(ctxt, root);
5710
5711     return(ctxt->err);
5712 }
5713
5714 /************************************************************************
5715  *                                                                      *
5716  *                      SAX Validation code                             *
5717  *                                                                      *
5718  ************************************************************************/
5719
5720 /************************************************************************
5721  *                                                                      *
5722  *                      Validation interfaces                           *
5723  *                                                                      *
5724  ************************************************************************/
5725
5726 /**
5727  * xmlSchemaNewValidCtxt:
5728  * @schema:  a precompiled XML Schemas
5729  *
5730  * Create an XML Schemas validation context based on the given schema
5731  *
5732  * Returns the validation context or NULL in case of error
5733  */
5734 xmlSchemaValidCtxtPtr
5735 xmlSchemaNewValidCtxt(xmlSchemaPtr schema) {
5736     xmlSchemaValidCtxtPtr ret;
5737
5738     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
5739     if (ret == NULL) {
5740         xmlGenericError(xmlGenericErrorContext,
5741                 "Failed to allocate new schama validation context\n");
5742         return (NULL);
5743     }
5744     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
5745     ret->schema = schema;
5746     ret->attrNr = 0;
5747     ret->attrMax = 10;
5748     ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
5749                                                   sizeof(xmlSchemaAttrState));
5750     if (ret->attr == NULL) {
5751         free(ret);
5752         return(NULL);
5753     }
5754     memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
5755     return (ret);
5756 }
5757
5758 /**
5759  * xmlSchemaFreeValidCtxt:
5760  * @ctxt:  the schema validation context
5761  *
5762  * Free the resources associated to the schema validation context
5763  */
5764 void
5765 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) {
5766     if (ctxt == NULL)
5767         return;
5768     if (ctxt->attr != NULL)
5769         xmlFree(ctxt->attr);
5770     if (ctxt->value != NULL)
5771         xmlSchemaFreeValue(ctxt->value);
5772     xmlFree(ctxt);
5773 }
5774
5775 /**
5776  * xmlSchemaSetValidErrors:
5777  * @ctxt:  a schema validation context
5778  * @err:  the error function
5779  * @warn: the warning function
5780  * @ctx: the functions context
5781  *
5782  * Set the error and warning callback informations
5783  */
5784 void
5785 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
5786         xmlSchemaValidityErrorFunc err,
5787         xmlSchemaValidityWarningFunc warn, void *ctx) {
5788     if (ctxt == NULL)
5789         return;
5790     ctxt->error = err;
5791     ctxt->warning = warn;
5792     ctxt->userData = ctx;
5793 }
5794
5795 /**
5796  * xmlSchemaValidateDoc:
5797  * @ctxt:  a schema validation context
5798  * @doc:  a parsed document tree
5799  *
5800  * Validate a document tree in memory.
5801  *
5802  * Returns 0 if the document is schemas valid, a positive error code
5803  *     number otherwise and -1 in case of internal or API error.
5804  */
5805 int
5806 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5807     int ret;
5808
5809     if ((ctxt == NULL) || (doc == NULL))
5810         return(-1);
5811
5812     ctxt->doc = doc;
5813     ret = xmlSchemaValidateDocument(ctxt, doc);
5814     return(ret);
5815 }
5816
5817 /**
5818  * xmlSchemaValidateStream:
5819  * @ctxt:  a schema validation context
5820  * @input:  the input to use for reading the data
5821  * @enc:  an optional encoding information
5822  * @sax:  a SAX handler for the resulting events
5823  * @user_data:  the context to provide to the SAX handler.
5824  *
5825  * Validate a document tree in memory.
5826  *
5827  * Returns 0 if the document is schemas valid, a positive error code
5828  *     number otherwise and -1 in case of internal or API error.
5829  */
5830 int     
5831 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
5832         xmlParserInputBufferPtr input, xmlCharEncoding enc,
5833         xmlSAXHandlerPtr sax, void *user_data) {
5834     if ((ctxt == NULL) || (input == NULL))
5835         return(-1);
5836     ctxt->input = input;
5837     ctxt->enc = enc;
5838     ctxt->sax = sax;
5839     ctxt->user_data = user_data;
5840     TODO
5841     return(0);
5842 }
5843
5844 #endif /* LIBXML_SCHEMAS_ENABLED */