blob: 38b92d32730a7b1d17ec9d54c6eaaa43070e26f6 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
10#define IN_LIBXML
11#include "libxml.h"
12
13#ifdef LIBXML_SCHEMAS_ENABLED
14
15#include <string.h>
16#include <libxml/xmlmemory.h>
17#include <libxml/parser.h>
18#include <libxml/parserInternals.h>
19#include <libxml/hash.h>
20
21#include <libxml/xmlschemas.h>
22#include <libxml/schemasInternals.h>
23#include <libxml/xmlschemastypes.h>
24#include <libxml/xmlautomata.h>
25#include <libxml/xmlregexp.h>
26
Daniel Veillard8651f532002-04-17 09:06:27 +000027#define DEBUG 1 /* very verbose output */
28#define DEBUG_CONTENT 1
29#define DEBUG_TYPE 1
Daniel Veillard4255d502002-04-16 15:50:10 +000030/* #define DEBUG_AUTOMATA 1 */
31
32#define UNBOUNDED (1 << 30)
33#define TODO \
34 xmlGenericError(xmlGenericErrorContext, \
35 "Unimplemented block at %s:%d\n", \
36 __FILE__, __LINE__);
37
38/*
39 * The XML Schemas namespaces
40 */
41static const xmlChar *xmlSchemaNs = (const xmlChar *)
42 "http://www.w3.org/2001/XMLSchema";
43
44static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
45 "http://www.w3.org/2001/XMLSchema-instance";
46
47#define IS_SCHEMA(node, type) \
48 ((node != NULL) && (node->ns != NULL) && \
49 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
50 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
51
52#define XML_SCHEMAS_PARSE_ERROR 1
53
54struct _xmlSchemaParserCtxt {
55 void *userData; /* user specific data block */
56 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
57 xmlSchemaValidityWarningFunc warning;/* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +000058 xmlSchemaValidError err;
Daniel Veillard4255d502002-04-16 15:50:10 +000059
60 xmlSchemaPtr schema; /* The schema in use */
61 xmlChar *container; /* the current element, group, ... */
62 int counter;
63
64 xmlChar *URL;
65 xmlDocPtr doc;
66
67 /*
68 * Used to build complex element content models
69 */
70 xmlAutomataPtr am;
71 xmlAutomataStatePtr start;
72 xmlAutomataStatePtr end;
73 xmlAutomataStatePtr state;
74};
75
76
77#define XML_SCHEMAS_ATTR_UNKNOWN 1
78#define XML_SCHEMAS_ATTR_CHECKED 2
79
80typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
81typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
82struct _xmlSchemaAttrState {
83 xmlAttrPtr attr;
84 int state;
85};
86
87/**
88 * xmlSchemaValidCtxt:
89 *
90 * A Schemas validation context
91 */
92
93struct _xmlSchemaValidCtxt {
94 void *userData; /* user specific data block */
95 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
96 xmlSchemaValidityWarningFunc warning;/* the callback in case of warning */
97
98 xmlSchemaPtr schema; /* The schema in use */
99 xmlDocPtr doc;
100 xmlParserInputBufferPtr input;
101 xmlCharEncoding enc;
102 xmlSAXHandlerPtr sax;
103 void *user_data;
104
105 xmlDocPtr myDoc;
106 int err;
107
108 xmlNodePtr node;
109 xmlSchemaTypePtr type;
110
111 xmlRegExecCtxtPtr regexp;
112 xmlSchemaValPtr value;
113
114 int attrNr;
115 int attrBase;
116 int attrMax;
117 xmlSchemaAttrStatePtr attr;
118};
119
120
121/************************************************************************
122 * *
123 * Some predeclarations *
124 * *
125 ************************************************************************/
126static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
127 xmlSchemaTypePtr type,
128 xmlChar *value);
129
130/************************************************************************
131 * *
132 * Allocation functions *
133 * *
134 ************************************************************************/
135
136/**
137 * xmlSchemaNewSchema:
138 * @ctxt: a schema validation context (optional)
139 *
140 * Allocate a new Schema structure.
141 *
142 * Returns the newly allocated structure or NULL in case or error
143 */
144static xmlSchemaPtr
145xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
146{
147 xmlSchemaPtr ret;
148
149 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
150 if (ret == NULL) {
151 if ((ctxt != NULL) && (ctxt->error != NULL))
152 ctxt->error(ctxt->userData, "Out of memory\n");
153 return (NULL);
154 }
155 memset(ret, 0, sizeof(xmlSchema));
156
157 return (ret);
158}
159
160/**
161 * xmlSchemaNewFacet:
162 * @ctxt: a schema validation context (optional)
163 *
164 * Allocate a new Facet structure.
165 *
166 * Returns the newly allocated structure or NULL in case or error
167 */
168static xmlSchemaFacetPtr
169xmlSchemaNewFacet(xmlSchemaParserCtxtPtr ctxt)
170{
171 xmlSchemaFacetPtr ret;
172
173 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
174 if (ret == NULL) {
175 if ((ctxt != NULL) && (ctxt->error != NULL))
176 ctxt->error(ctxt->userData, "Out of memory\n");
177 return (NULL);
178 }
179 memset(ret, 0, sizeof(xmlSchemaFacet));
180
181 return (ret);
182}
183
184/**
185 * xmlSchemaNewAnnot:
186 * @ctxt: a schema validation context (optional)
187 * @node: a node
188 *
189 * Allocate a new annotation structure.
190 *
191 * Returns the newly allocated structure or NULL in case or error
192 */
193static xmlSchemaAnnotPtr
194xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
195{
196 xmlSchemaAnnotPtr ret;
197
198 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
199 if (ret == NULL) {
200 if ((ctxt != NULL) && (ctxt->error != NULL))
201 ctxt->error(ctxt->userData, "Out of memory\n");
202 return (NULL);
203 }
204 memset(ret, 0, sizeof(xmlSchemaAnnot));
205 ret->content = node;
206 return (ret);
207}
208
209/**
210 * xmlSchemaFreeNotation:
211 * @schema: a schema notation structure
212 *
213 * Deallocate a Schema Notation structure.
214 */
215static void
216xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
217{
218 if (nota == NULL)
219 return;
220 if (nota->name != NULL)
221 xmlFree((xmlChar *) nota->name);
222 xmlFree(nota);
223}
224
225/**
226 * xmlSchemaFreeAttribute:
227 * @schema: a schema attribute structure
228 *
229 * Deallocate a Schema Attribute structure.
230 */
231static void
232xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
233{
234 if (attr == NULL)
235 return;
236 if (attr->name != NULL)
237 xmlFree((xmlChar *) attr->name);
238 if (attr->ref != NULL)
239 xmlFree((xmlChar *) attr->ref);
240 if (attr->refNs != NULL)
241 xmlFree((xmlChar *) attr->refNs);
242 if (attr->typeName != NULL)
243 xmlFree((xmlChar *) attr->typeName);
244 if (attr->typeNs != NULL)
245 xmlFree((xmlChar *) attr->typeNs);
246 xmlFree(attr);
247}
248
249/**
250 * xmlSchemaFreeAttributeGroup:
251 * @schema: a schema attribute group structure
252 *
253 * Deallocate a Schema Attribute Group structure.
254 */
255static void
256xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
257{
258 if (attr == NULL)
259 return;
260 if (attr->name != NULL)
261 xmlFree((xmlChar *) attr->name);
262 xmlFree(attr);
263}
264
265/**
266 * xmlSchemaFreeElement:
267 * @schema: a schema element structure
268 *
269 * Deallocate a Schema Element structure.
270 */
271static void
272xmlSchemaFreeElement(xmlSchemaElementPtr elem)
273{
274 if (elem == NULL)
275 return;
276 if (elem->name != NULL)
277 xmlFree((xmlChar *) elem->name);
278 if (elem->namedType != NULL)
279 xmlFree((xmlChar *) elem->namedType);
280 if (elem->namedTypeNs != NULL)
281 xmlFree((xmlChar *) elem->namedTypeNs);
282 if (elem->ref != NULL)
283 xmlFree((xmlChar *) elem->ref);
284 if (elem->refNs != NULL)
285 xmlFree((xmlChar *) elem->refNs);
286 if (elem->contModel != NULL)
287 xmlRegFreeRegexp(elem->contModel);
288 xmlFree(elem);
289}
290
291/**
292 * xmlSchemaFreeFacet:
293 * @facet: a schema facet structure
294 *
295 * Deallocate a Schema Facet structure.
296 */
297static void
298xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
299{
300 if (facet == NULL)
301 return;
302 if (facet->value != NULL)
303 xmlFree((xmlChar *) facet->value);
304 if (facet->id != NULL)
305 xmlFree((xmlChar *) facet->id);
306 if (facet->val != NULL)
307 xmlSchemaFreeValue(facet->val);
308 if (facet->regexp != NULL)
309 xmlRegFreeRegexp(facet->regexp);
310 xmlFree(facet);
311}
312
313/**
314 * xmlSchemaFreeType:
315 * @type: a schema type structure
316 *
317 * Deallocate a Schema Type structure.
318 */
319void
320xmlSchemaFreeType(xmlSchemaTypePtr type)
321{
322 if (type == NULL)
323 return;
324 if (type->name != NULL)
325 xmlFree((xmlChar *) type->name);
326 if (type->base != NULL)
327 xmlFree((xmlChar *) type->base);
328 if (type->baseNs != NULL)
329 xmlFree((xmlChar *) type->baseNs);
330 if (type->annot != NULL)
331 xmlFree((xmlChar *) type->annot);
332 if (type->facets != NULL) {
333 xmlSchemaFacetPtr facet, next;
334
335 facet = type->facets;
336 while (facet != NULL) {
337 next = facet->next;
338 xmlSchemaFreeFacet(facet);
339 facet = next;
340 }
341 }
342 xmlFree(type);
343}
344
345/**
346 * xmlSchemaFreeAnnot:
347 * @annot: a schema type structure
348 *
349 * Deallocate a annotation structure
350 */
351static void
352xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
353{
354 if (annot == NULL)
355 return;
356 xmlFree(annot);
357}
358
359/**
360 * xmlSchemaFree:
361 * @schema: a schema structure
362 *
363 * Deallocate a Schema structure.
364 */
365void
366xmlSchemaFree(xmlSchemaPtr schema)
367{
368 if (schema == NULL)
369 return;
370
371 if (schema->name != NULL)
372 xmlFree((xmlChar *) schema->name);
373 if (schema->notaDecl != NULL)
374 xmlHashFree(schema->notaDecl,
375 (xmlHashDeallocator) xmlSchemaFreeNotation);
376 if (schema->attrDecl != NULL)
377 xmlHashFree(schema->attrDecl,
378 (xmlHashDeallocator) xmlSchemaFreeAttribute);
379 if (schema->attrgrpDecl != NULL)
380 xmlHashFree(schema->attrgrpDecl,
381 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
382 if (schema->elemDecl != NULL)
383 xmlHashFree(schema->elemDecl,
384 (xmlHashDeallocator) xmlSchemaFreeElement);
385 if (schema->typeDecl != NULL)
386 xmlHashFree(schema->typeDecl,
387 (xmlHashDeallocator) xmlSchemaFreeType);
388 if (schema->annot != NULL)
389 xmlSchemaFreeAnnot(schema->annot);
390 if (schema->doc != NULL)
391 xmlFreeDoc(schema->doc);
392
393 xmlFree(schema);
394}
395
396/************************************************************************
397 * *
398 * Error functions *
399 * *
400 ************************************************************************/
401
402/**
403 * xmlSchemaErrorContext:
404 * @ctxt: the parsing context
405 * @schema: the schema being built
406 * @node: the node being processed
407 * @child: the child being processed
408 *
409 * Dump a SchemaType structure
410 */
411static void
412xmlSchemaErrorContext(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
413 xmlNodePtr node, xmlNodePtr child)
414{
415 int line = 0;
416 const xmlChar *file = NULL;
417 const xmlChar *name = NULL;
418 const char *type = "error";
419
420 if ((ctxt == NULL) || (ctxt->error == NULL))
421 return;
422
423 if (child != NULL)
424 node = child;
425
426 if (node != NULL) {
427 if ((node->type == XML_DOCUMENT_NODE) ||
428 (node->type == XML_HTML_DOCUMENT_NODE)) {
429 xmlDocPtr doc = (xmlDocPtr) node;
430
431 file = doc->URL;
432 } else {
433 /*
434 * Try to find contextual informations to report
435 */
436 if (node->type == XML_ELEMENT_NODE) {
437 line = (int) node->content;
438 } else if ((node->prev != NULL) &&
439 (node->prev->type == XML_ELEMENT_NODE)) {
440 line = (int) node->prev->content;
441 } else if ((node->parent != NULL) &&
442 (node->parent->type == XML_ELEMENT_NODE)) {
443 line = (int) node->parent->content;
444 }
445 if ((node->doc != NULL) && (node->doc->URL != NULL))
446 file = node->doc->URL;
447 if (node->name != NULL)
448 name = node->name;
449 }
450 }
451
452 if (ctxt != NULL)
453 type = "compilation error";
454 else if (schema != NULL)
455 type = "runtime error";
456
457 if ((file != NULL) && (line != 0) && (name != NULL))
458 ctxt->error(ctxt->userData, "%s: file %s line %d element %s\n",
459 type, file, line, name);
460 else if ((file != NULL) && (name != NULL))
461 ctxt->error(ctxt->userData, "%s: file %s element %s\n",
462 type, file, name);
463 else if ((file != NULL) && (line != 0))
464 ctxt->error(ctxt->userData, "%s: file %s line %d\n", type, file, line);
465 else if (file != NULL)
466 ctxt->error(ctxt->userData, "%s: file %s\n", type, file);
467 else if (name != NULL)
468 ctxt->error(ctxt->userData, "%s: element %s\n", type, name);
469 else
470 ctxt->error(ctxt->userData, "%s\n", type);
471}
472
473/************************************************************************
474 * *
475 * Debug functions *
476 * *
477 ************************************************************************/
478
479/**
480 * xmlSchemaElementDump:
481 * @elem: an element
482 * @output: the file output
483 *
484 * Dump the element
485 */
486static void
487xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
488 ATTRIBUTE_UNUSED const xmlChar *name,
489 ATTRIBUTE_UNUSED const xmlChar *context,
490 ATTRIBUTE_UNUSED const xmlChar *namespace)
491{
492 if (elem == NULL)
493 return;
494
495 fprintf(output, "Element ");
496 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
497 fprintf(output, "toplevel ");
498 fprintf(output, ": %s ", elem->name);
499 if (namespace != NULL)
500 fprintf(output, "namespace '%s' ", namespace);
501
502 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
503 fprintf(output, "nillable ");
504 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
505 fprintf(output, "global ");
506 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
507 fprintf(output, "default ");
508 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
509 fprintf(output, "fixed ");
510 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
511 fprintf(output, "abstract ");
512 if (elem->flags & XML_SCHEMAS_ELEM_REF)
513 fprintf(output, "ref '%s' ", elem->ref);
514 if (elem->id != NULL)
515 fprintf(output, "id '%s' ", elem->id);
516 fprintf(output, "\n");
517 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
518 fprintf(output, " ");
519 if (elem->minOccurs != 1)
520 fprintf(output, "min: %d ", elem->minOccurs);
521 if (elem->maxOccurs >= UNBOUNDED)
522 fprintf(output, "max: unbounded\n");
523 else if (elem->maxOccurs != 1)
524 fprintf(output, "max: %d\n", elem->maxOccurs);
525 else
526 fprintf(output, "\n");
527 }
528 if (elem->namedType != NULL) {
529 fprintf(output, " type: %s", elem->namedType);
530 if (elem->namedTypeNs != NULL)
531 fprintf(output, " ns %s\n", elem->namedTypeNs);
532 else
533 fprintf(output, "\n");
534 }
535 if (elem->substGroup != NULL) {
536 fprintf(output, " substitutionGroup: %s", elem->substGroup);
537 if (elem->substGroupNs != NULL)
538 fprintf(output, " ns %s\n", elem->substGroupNs);
539 else
540 fprintf(output, "\n");
541 }
542 if (elem->value != NULL)
543 fprintf(output, " default: %s", elem->value);
544}
545
546/**
547 * xmlSchemaAnnotDump:
548 * @output: the file output
549 * @annot: a annotation
550 *
551 * Dump the annotation
552 */
553static void
554xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
555{
556 xmlChar *content;
557
558 if (annot == NULL)
559 return;
560
561 content = xmlNodeGetContent(annot->content);
562 if (content != NULL) {
563 fprintf(output, " Annot: %s\n", content);
564 xmlFree(content);
565 } else
566 fprintf(output, " Annot: empty\n");
567}
568
569/**
570 * xmlSchemaTypeDump:
571 * @output: the file output
572 * @type: a type structure
573 *
574 * Dump a SchemaType structure
575 */
576static void
577xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
578{
579 if (type == NULL) {
580 fprintf(output, "Type: NULL\n");
581 return;
582 }
583 fprintf(output, "Type: ");
584 if (type->name != NULL)
585 fprintf(output, "%s, ", type->name);
586 else
587 fprintf(output, "no name");
588 switch (type->type) {
589 case XML_SCHEMA_TYPE_BASIC:
590 fprintf(output, "basic ");
591 break;
592 case XML_SCHEMA_TYPE_SIMPLE:
593 fprintf(output, "simple ");
594 break;
595 case XML_SCHEMA_TYPE_COMPLEX:
596 fprintf(output, "complex ");
597 break;
598 case XML_SCHEMA_TYPE_SEQUENCE:
599 fprintf(output, "sequence ");
600 break;
601 case XML_SCHEMA_TYPE_CHOICE:
602 fprintf(output, "choice ");
603 break;
604 case XML_SCHEMA_TYPE_ALL:
605 fprintf(output, "all ");
606 break;
607 case XML_SCHEMA_TYPE_UR:
608 fprintf(output, "ur ");
609 break;
610 case XML_SCHEMA_TYPE_RESTRICTION:
611 fprintf(output, "restriction ");
612 break;
613 case XML_SCHEMA_TYPE_EXTENSION:
614 fprintf(output, "extension ");
615 break;
616 default:
617 fprintf(output, "unknowntype%d ", type->type);
618 break;
619 }
620 if (type->base != NULL) {
621 fprintf(output, "base %s, ", type->base);
622 }
623 switch (type->contentType) {
624 case XML_SCHEMA_CONTENT_UNKNOWN:
625 fprintf(output, "unknown ");
626 break;
627 case XML_SCHEMA_CONTENT_EMPTY:
628 fprintf(output, "empty ");
629 break;
630 case XML_SCHEMA_CONTENT_ELEMENTS:
631 fprintf(output, "element ");
632 break;
633 case XML_SCHEMA_CONTENT_MIXED:
634 fprintf(output, "mixed ");
635 break;
636 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
637 fprintf(output, "mixed_or_elems ");
638 break;
639 case XML_SCHEMA_CONTENT_BASIC:
640 fprintf(output, "basic ");
641 break;
642 case XML_SCHEMA_CONTENT_SIMPLE:
643 fprintf(output, "simple ");
644 break;
Daniel Veillard88c58912002-04-23 07:12:20 +0000645 case XML_SCHEMA_CONTENT_ANY:
646 fprintf(output, "any ");
647 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000648 }
649 fprintf(output, "\n");
650 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
651 fprintf(output, " ");
652 if (type->minOccurs != 1)
653 fprintf(output, "min: %d ", type->minOccurs);
654 if (type->maxOccurs >= UNBOUNDED)
655 fprintf(output, "max: unbounded\n");
656 else if (type->maxOccurs != 1)
657 fprintf(output, "max: %d\n", type->maxOccurs);
658 else
659 fprintf(output, "\n");
660 }
661 if (type->annot != NULL)
662 xmlSchemaAnnotDump(output, type->annot);
663 if (type->subtypes != NULL) {
664 xmlSchemaTypePtr sub = type->subtypes;
665
666 fprintf(output, " subtypes: ");
667 while (sub != NULL) {
668 fprintf(output, "%s ", sub->name);
669 sub = sub->next;
670 }
671 fprintf(output, "\n");
672 }
673
674}
675
676/**
677 * xmlSchemaDump:
678 * @output: the file output
679 * @schema: a schema structure
680 *
681 * Dump a Schema structure.
682 */
683void
684xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
685{
686 if (schema == NULL) {
687 fprintf(output, "Schemas: NULL\n");
688 return;
689 }
690 fprintf(output, "Schemas: ");
691 if (schema->name != NULL)
692 fprintf(output, "%s, ", schema->name);
693 else
694 fprintf(output, "no name, ");
695 if (schema->targetNamespace != NULL)
696 fprintf(output, "%s", schema->targetNamespace);
697 else
698 fprintf(output, "no target namespace");
699 fprintf(output, "\n");
700 if (schema->annot != NULL)
701 xmlSchemaAnnotDump(output, schema->annot);
702
703 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
704 output);
705 xmlHashScanFull(schema->elemDecl,
706 (xmlHashScannerFull) xmlSchemaElementDump, output);
707}
708
709/************************************************************************
710 * *
711 * Parsing functions *
712 * *
713 ************************************************************************/
714
715/**
716 * xmlSchemaGetType:
717 * @schema: the schemas context
718 * @name: the type name
719 * @ns: the type namespace
720 *
721 * Lookup a type in the schemas or the predefined types
722 *
723 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
724 */
725static xmlSchemaTypePtr
726xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
727 const xmlChar * namespace) {
728 xmlSchemaTypePtr ret;
729
730 if (name == NULL)
731 return(NULL);
732 if (schema != NULL) {
733 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
734 if (ret != NULL)
735 return(ret);
736 }
737 ret = xmlSchemaGetPredefinedType(name, namespace);
738#ifdef DEBUG
739 if (ret == NULL) {
740 if (namespace == NULL)
741 fprintf(stderr, "Unable to lookup type %s", name);
742 else
743 fprintf(stderr, "Unable to lookup type %s:%s", name, namespace);
744 }
745#endif
746 return(ret);
747}
748
749/************************************************************************
750 * *
751 * Parsing functions *
752 * *
753 ************************************************************************/
754
755#define IS_BLANK_NODE(n) \
756 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
757
758/**
759 * xmlSchemaIsBlank:
760 * @str: a string
761 *
762 * Check if a string is ignorable
763 *
764 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
765 */
766static int
767xmlSchemaIsBlank(xmlChar *str) {
768 if (str == NULL)
769 return(1);
770 while (*str != 0) {
771 if (!(IS_BLANK(*str))) return(0);
772 str++;
773 }
774 return(1);
775}
776
777/**
778 * xmlSchemaAddNotation:
779 * @ctxt: a schema validation context
780 * @schema: the schema being built
781 * @name: the item name
782 *
783 * Add an XML schema Attrribute declaration
784 * *WARNING* this interface is highly subject to change
785 *
786 * Returns the new struture or NULL in case of error
787 */
788static xmlSchemaNotationPtr
789xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
790 const xmlChar * name)
791{
792 xmlSchemaNotationPtr ret = NULL;
793 int val;
794
795 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
796 return (NULL);
797
798 if (schema->notaDecl == NULL)
799 schema->notaDecl = xmlHashCreate(10);
800 if (schema->notaDecl == NULL)
801 return (NULL);
802
803 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
804 if (ret == NULL) {
805 if ((ctxt != NULL) && (ctxt->error != NULL))
806 ctxt->error(ctxt->userData, "Out of memory\n");
807 return (NULL);
808 }
809 memset(ret, 0, sizeof(xmlSchemaNotation));
810 ret->name = xmlStrdup(name);
811 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
812 ret);
813 if (val != 0) {
814 if ((ctxt != NULL) && (ctxt->error != NULL))
815 ctxt->error(ctxt->userData, "Could not add notation %s\n",
816 name);
817 xmlFree((char *) ret->name);
818 xmlFree(ret);
819 return (NULL);
820 }
821 return (ret);
822}
823
824
825/**
826 * xmlSchemaAddAttribute:
827 * @ctxt: a schema validation context
828 * @schema: the schema being built
829 * @name: the item name
830 * @container: the container's name
831 *
832 * Add an XML schema Attrribute declaration
833 * *WARNING* this interface is highly subject to change
834 *
835 * Returns the new struture or NULL in case of error
836 */
837static xmlSchemaAttributePtr
838xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
839 const xmlChar * name)
840{
841 xmlSchemaAttributePtr ret = NULL;
842 int val;
843
844 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
845 return (NULL);
846
847 if (schema->attrDecl == NULL)
848 schema->attrDecl = xmlHashCreate(10);
849 if (schema->attrDecl == NULL)
850 return (NULL);
851
852 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
853 if (ret == NULL) {
854 if ((ctxt != NULL) && (ctxt->error != NULL))
855 ctxt->error(ctxt->userData, "Out of memory\n");
856 return (NULL);
857 }
858 memset(ret, 0, sizeof(xmlSchemaAttribute));
859 ret->name = xmlStrdup(name);
860 val = xmlHashAddEntry3(schema->attrDecl, name,
861 schema->targetNamespace, ctxt->container, ret);
862 if (val != 0) {
863 if ((ctxt != NULL) && (ctxt->error != NULL))
864 ctxt->error(ctxt->userData, "Could not add attribute %s\n",
865 name);
866 xmlFree((char *) ret->name);
867 xmlFree(ret);
868 return (NULL);
869 }
870 return (ret);
871}
872
873/**
874 * xmlSchemaAddAttributeGroup:
875 * @ctxt: a schema validation context
876 * @schema: the schema being built
877 * @name: the item name
878 *
879 * Add an XML schema Attrribute Group declaration
880 *
881 * Returns the new struture or NULL in case of error
882 */
883static xmlSchemaAttributeGroupPtr
884xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
885 const xmlChar * name)
886{
887 xmlSchemaAttributeGroupPtr ret = NULL;
888 int val;
889
890 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
891 return (NULL);
892
893 if (schema->attrgrpDecl == NULL)
894 schema->attrgrpDecl = xmlHashCreate(10);
895 if (schema->attrgrpDecl == NULL)
896 return (NULL);
897
898 ret = (xmlSchemaAttributeGroupPtr) xmlMalloc(sizeof(xmlSchemaAttributeGroup));
899 if (ret == NULL) {
900 if ((ctxt != NULL) && (ctxt->error != NULL))
901 ctxt->error(ctxt->userData, "Out of memory\n");
902 return (NULL);
903 }
904 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
905 ret->name = xmlStrdup(name);
906 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
907 schema->targetNamespace, ctxt->container, ret);
908 if (val != 0) {
909 if ((ctxt != NULL) && (ctxt->error != NULL))
910 ctxt->error(ctxt->userData, "Could not add attribute group %s\n",
911 name);
912 xmlFree((char *) ret->name);
913 xmlFree(ret);
914 return (NULL);
915 }
916 return (ret);
917}
918
919/**
920 * xmlSchemaAddElement:
921 * @ctxt: a schema validation context
922 * @schema: the schema being built
923 * @name: the type name
924 * @namespace: the type namespace
925 *
926 * Add an XML schema Element declaration
927 * *WARNING* this interface is highly subject to change
928 *
929 * Returns the new struture or NULL in case of error
930 */
931static xmlSchemaElementPtr
932xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
933 const xmlChar * name, const xmlChar * namespace)
934{
935 xmlSchemaElementPtr ret = NULL;
936 int val;
937
938 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
939 return (NULL);
940
941 if (schema->elemDecl == NULL)
942 schema->elemDecl = xmlHashCreate(10);
943 if (schema->elemDecl == NULL)
944 return (NULL);
945
946 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
947 if (ret == NULL) {
948 if ((ctxt != NULL) && (ctxt->error != NULL))
949 ctxt->error(ctxt->userData, "Out of memory\n");
950 return (NULL);
951 }
952 memset(ret, 0, sizeof(xmlSchemaElement));
953 ret->name = xmlStrdup(name);
954 val = xmlHashAddEntry3(schema->elemDecl, name,
955 namespace, ctxt->container, ret);
956 if (val != 0) {
957 char buf[100];
958
959 snprintf(buf, 99, "privatieelem%d", ctxt->counter++ + 1);
960 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
961 namespace, ret);
962 if (val != 0) {
963 if ((ctxt != NULL) && (ctxt->error != NULL))
964 ctxt->error(ctxt->userData, "Could not add element %s\n",
965 name);
966 xmlFree((char *) ret->name);
967 xmlFree(ret);
968 return (NULL);
969 }
970 }
971 return (ret);
972}
973
974/**
975 * xmlSchemaAddType:
976 * @ctxt: a schema validation context
977 * @schema: the schema being built
978 * @name: the item name
979 *
980 * Add an XML schema Simple Type definition
981 * *WARNING* this interface is highly subject to change
982 *
983 * Returns the new struture or NULL in case of error
984 */
985static xmlSchemaTypePtr
986xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
987 const xmlChar * name)
988{
989 xmlSchemaTypePtr ret = NULL;
990 int val;
991
992 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
993 return (NULL);
994
995 if (schema->typeDecl == NULL)
996 schema->typeDecl = xmlHashCreate(10);
997 if (schema->typeDecl == NULL)
998 return (NULL);
999
1000 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1001 if (ret == NULL) {
1002 if ((ctxt != NULL) && (ctxt->error != NULL))
1003 ctxt->error(ctxt->userData, "Out of memory\n");
1004 return (NULL);
1005 }
1006 memset(ret, 0, sizeof(xmlSchemaType));
1007 ret->name = xmlStrdup(name);
1008 val = xmlHashAddEntry2(schema->typeDecl, name, schema->targetNamespace,
1009 ret);
1010 if (val != 0) {
1011 if ((ctxt != NULL) && (ctxt->error != NULL))
1012 ctxt->error(ctxt->userData, "Could not add type %s\n", name);
1013 xmlFree((char *) ret->name);
1014 xmlFree(ret);
1015 return (NULL);
1016 }
1017 ret->minOccurs = 1;
1018 ret->maxOccurs = 1;
1019
1020 return (ret);
1021}
1022
1023/************************************************************************
1024 * *
1025 * Utilities for parsing *
1026 * *
1027 ************************************************************************/
1028
1029/**
1030 * xmlGetQNameProp:
1031 * @ctxt: a schema validation context
1032 * @node: a subtree containing XML Schema informations
1033 * @name: the attribute name
1034 * @namespace: the result namespace if any
1035 *
1036 * Extract a QName Attribute value
1037 *
1038 * Returns the NCName or NULL if not found, and also update @namespace
1039 * with the namespace URI
1040 */
1041static xmlChar *
1042xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1043 const char *name,
1044 xmlChar **namespace) {
1045 xmlChar *val, *ret, *prefix;
1046 xmlNsPtr ns;
1047
1048
1049 if (namespace != NULL)
1050 *namespace = NULL;
1051 val = xmlGetProp(node, (const xmlChar *) name);
1052 if (val == NULL)
1053 return(NULL);
1054
1055 ret = xmlSplitQName2(val, &prefix);
1056 if (ret == NULL)
1057 return(val);
1058 xmlFree(val);
1059
1060 ns = xmlSearchNs(node->doc, node, prefix);
1061 if (ns == NULL) {
1062 xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1063 if ((ctxt != NULL) && (ctxt->error != NULL))
1064 ctxt->error(ctxt->userData,
1065 "Attribute %s: the QName prefix %s is undefined\n",
1066 name, prefix);
1067 } else {
1068 *namespace = xmlStrdup(ns->href);
1069 }
1070 xmlFree(prefix);
1071 return(ret);
1072}
1073
1074/**
1075 * xmlGetMaxOccurs:
1076 * @ctxt: a schema validation context
1077 * @node: a subtree containing XML Schema informations
1078 *
1079 * Get the maxOccurs property
1080 *
1081 * Returns the default if not found, or the value
1082 */
1083static int
1084xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) {
1085 xmlChar *val, *cur;
1086 int ret = 0;
1087
1088 val = xmlGetProp(node, (const xmlChar *) "maxOccurs");
1089 if (val == NULL)
1090 return(1);
1091
1092 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
1093 xmlFree(val);
1094 return(UNBOUNDED); /* encoding it with -1 might be another option */
1095 }
1096
1097 cur = val;
1098 while (IS_BLANK(*cur)) cur++;
1099 while ((*cur >= '0') && (*cur <= '9')) {
1100 ret = ret * 10 + (*cur - '0');
1101 cur++;
1102 }
1103 while (IS_BLANK(*cur)) cur++;
1104 if (*cur != 0) {
1105 xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1106 if ((ctxt != NULL) && (ctxt->error != NULL))
1107 ctxt->error(ctxt->userData, "invalid value for minOccurs: %s\n",
1108 val);
1109 xmlFree(val);
1110 return(1);
1111 }
1112 xmlFree(val);
1113 return(ret);
1114}
1115
1116/**
1117 * xmlGetMinOccurs:
1118 * @ctxt: a schema validation context
1119 * @node: a subtree containing XML Schema informations
1120 *
1121 * Get the minOccurs property
1122 *
1123 * Returns the default if not found, or the value
1124 */
1125static int
1126xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) {
1127 xmlChar *val, *cur;
1128 int ret = 0;
1129
1130 val = xmlGetProp(node, (const xmlChar *) "minOccurs");
1131 if (val == NULL)
1132 return(1);
1133
1134 cur = val;
1135 while (IS_BLANK(*cur)) cur++;
1136 while ((*cur >= '0') && (*cur <= '9')) {
1137 ret = ret * 10 + (*cur - '0');
1138 cur++;
1139 }
1140 while (IS_BLANK(*cur)) cur++;
1141 if (*cur != 0) {
1142 xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1143 if ((ctxt != NULL) && (ctxt->error != NULL))
1144 ctxt->error(ctxt->userData, "invalid value for minOccurs: %s\n",
1145 val);
1146 xmlFree(val);
1147 return(1);
1148 }
1149 xmlFree(val);
1150 return(ret);
1151}
1152
1153/**
1154 * xmlGetBooleanProp:
1155 * @ctxt: a schema validation context
1156 * @node: a subtree containing XML Schema informations
1157 * @name: the attribute name
1158 * @def: the default value
1159 *
1160 * Get is a bolean property is set
1161 *
1162 * Returns the default if not found, 0 if found to be false,
1163 * 1 if found to be true
1164 */
1165static int
1166xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1167 const char *name, int def) {
1168 xmlChar *val;
1169
1170 val = xmlGetProp(node, (const xmlChar *) name);
1171 if (val == NULL)
1172 return(def);
1173
1174 if (xmlStrEqual(val, BAD_CAST"true"))
1175 def = 1;
1176 else if (xmlStrEqual(val, BAD_CAST"false"))
1177 def = 0;
1178 else {
1179 xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1180 if ((ctxt != NULL) && (ctxt->error != NULL))
1181 ctxt->error(ctxt->userData,
1182 "Attribute %s: the value %s is not boolean\n",
1183 name, val);
1184 }
1185 xmlFree(val);
1186 return(def);
1187}
1188
1189/************************************************************************
1190 * *
1191 * Shema extraction from an Infoset *
1192 * *
1193 ************************************************************************/
1194static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1195 ctxt, xmlSchemaPtr schema,
1196 xmlNodePtr node);
1197static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,
1198 xmlSchemaPtr schema,
1199 xmlNodePtr node);
1200static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,
1201 xmlSchemaPtr schema,
1202 xmlNodePtr node,
1203 int simple);
1204static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1205 xmlSchemaPtr schema,
1206 xmlNodePtr node);
1207static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1208 xmlSchemaPtr schema,
1209 xmlNodePtr node);
1210static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1211 ctxt,
1212 xmlSchemaPtr schema,
1213 xmlNodePtr node);
1214static xmlSchemaAttributeGroupPtr
1215xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1216 xmlSchemaPtr schema, xmlNodePtr node);
1217static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1218 xmlSchemaPtr schema,
1219 xmlNodePtr node);
1220static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1221 xmlSchemaPtr schema,
1222 xmlNodePtr node);
1223static xmlSchemaAttributePtr
1224xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1225 xmlNodePtr node);
1226
1227/**
1228 * xmlSchemaParseAttrDecls:
1229 * @ctxt: a schema validation context
1230 * @schema: the schema being built
1231 * @node: a subtree containing XML Schema informations
1232 * @type: the hosting type
1233 *
1234 * parse a XML schema attrDecls declaration corresponding to
1235 * <!ENTITY % attrDecls
1236 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1237 */
1238static xmlNodePtr
1239xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1240 xmlNodePtr child, xmlSchemaTypePtr type)
1241{
1242 xmlSchemaAttributePtr lastattr, attr;
1243
1244 lastattr = NULL;
1245 while ((IS_SCHEMA(child, "attribute")) ||
1246 (IS_SCHEMA(child, "attributeGroup"))) {
1247 attr = NULL;
1248 if (IS_SCHEMA(child, "attribute")) {
1249 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1250 } else if (IS_SCHEMA(child, "attributeGroup")) {
1251 attr = (xmlSchemaAttributePtr)
1252 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1253 }
1254 if (attr != NULL) {
1255 if (lastattr == NULL) {
1256 type->attributes = attr;
1257 lastattr = attr
1258 ;
1259 } else {
1260 lastattr->next = attr;
1261 lastattr = attr;
1262 }
1263 }
1264 child = child->next;
1265 }
1266 if (IS_SCHEMA(child, "anyAttribute")) {
1267 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1268 if (attr != NULL) {
1269 if (lastattr == NULL) {
1270 type->attributes = attr;
1271 lastattr = attr
1272 ;
1273 } else {
1274 lastattr->next = attr;
1275 lastattr = attr;
1276 }
1277 }
1278 child = child->next;
1279 }
1280 return(child);
1281}
1282
1283/**
1284 * xmlSchemaParseAnnotation:
1285 * @ctxt: a schema validation context
1286 * @schema: the schema being built
1287 * @node: a subtree containing XML Schema informations
1288 *
1289 * parse a XML schema Attrribute declaration
1290 * *WARNING* this interface is highly subject to change
1291 *
1292 * Returns -1 in case of error, 0 if the declaration is inproper and
1293 * 1 in case of success.
1294 */
1295static xmlSchemaAnnotPtr
1296xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1297 xmlNodePtr node)
1298{
1299 xmlSchemaAnnotPtr ret;
1300
1301 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1302 return (NULL);
1303 ret = xmlSchemaNewAnnot(ctxt, node);
1304
1305 return (ret);
1306}
1307
1308/**
1309 * xmlSchemaParseFacet:
1310 * @ctxt: a schema validation context
1311 * @schema: the schema being built
1312 * @node: a subtree containing XML Schema informations
1313 *
1314 * parse a XML schema Facet declaration
1315 * *WARNING* this interface is highly subject to change
1316 *
1317 * Returns the new type structure or NULL in case of error
1318 */
1319static xmlSchemaFacetPtr
1320xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1321 xmlNodePtr node)
1322{
1323 xmlSchemaFacetPtr facet;
1324 xmlNodePtr child = NULL;
1325 xmlChar *value;
1326
1327 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1328 return (NULL);
1329
1330 facet = xmlSchemaNewFacet(ctxt);
1331 if (facet == NULL)
1332 return (NULL);
1333 facet->node = node;
1334 value = xmlGetProp(node, (const xmlChar *) "value");
1335 if (value == NULL) {
1336 xmlSchemaErrorContext(ctxt, schema, node, child);
1337 if ((ctxt != NULL) && (ctxt->error != NULL))
1338 ctxt->error(ctxt->userData, "Facet %s has no value\n", node->name);
1339 xmlSchemaFreeFacet(facet);
1340 return (NULL);
1341 }
1342 if (IS_SCHEMA(node, "minInclusive")) {
1343 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
1344 } else if (IS_SCHEMA(node, "minExclusive")) {
1345 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
1346 } else if (IS_SCHEMA(node, "maxInclusive")) {
1347 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
1348 } else if (IS_SCHEMA(node, "maxExclusive")) {
1349 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
1350 } else if (IS_SCHEMA(node, "totalDigits")) {
1351 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
1352 } else if (IS_SCHEMA(node, "fractionDigits")) {
1353 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
1354 } else if (IS_SCHEMA(node, "pattern")) {
1355 facet->type = XML_SCHEMA_FACET_PATTERN;
1356 } else if (IS_SCHEMA(node, "enumeration")) {
1357 facet->type = XML_SCHEMA_FACET_ENUMERATION;
1358 } else if (IS_SCHEMA(node, "whiteSpace")) {
1359 facet->type = XML_SCHEMA_FACET_WHITESPACE;
1360 } else if (IS_SCHEMA(node, "length")) {
1361 facet->type = XML_SCHEMA_FACET_LENGTH;
1362 } else if (IS_SCHEMA(node, "maxLength")) {
1363 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1364 } else if (IS_SCHEMA(node, "minLength")) {
1365 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1366 } else {
1367 xmlSchemaErrorContext(ctxt, schema, node, child);
1368 if ((ctxt != NULL) && (ctxt->error != NULL))
1369 ctxt->error(ctxt->userData, "Unknown facet type %s\n", node->name);
1370 xmlSchemaFreeFacet(facet);
1371 return(NULL);
1372 }
1373 facet->id = xmlGetProp(node, (const xmlChar *) "id");
1374 facet->value = value;
1375 child = node->children;
1376
1377 if (IS_SCHEMA(child, "annotation")) {
1378 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1379 child = child->next;
1380 }
1381 if (child != NULL) {
1382 xmlSchemaErrorContext(ctxt, schema, node, child);
1383 if ((ctxt != NULL) && (ctxt->error != NULL))
1384 ctxt->error(ctxt->userData,
1385 "Facet %s has unexpected child content\n",
1386 node->name);
1387 }
1388 return (facet);
1389}
1390
1391/**
1392 * xmlSchemaParseAny:
1393 * @ctxt: a schema validation context
1394 * @schema: the schema being built
1395 * @node: a subtree containing XML Schema informations
1396 *
1397 * parse a XML schema Any declaration
1398 * *WARNING* this interface is highly subject to change
1399 *
1400 * Returns the new type structure or NULL in case of error
1401 */
1402static xmlSchemaTypePtr
1403xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1404 xmlNodePtr node)
1405{
1406 xmlSchemaTypePtr type;
1407 xmlNodePtr child = NULL;
1408 xmlChar name[30];
1409
1410 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1411 return (NULL);
1412 snprintf((char *)name, 30, "any %d", ctxt->counter++ + 1);
1413 type = xmlSchemaAddType(ctxt, schema, name);
1414 if (type == NULL)
1415 return (NULL);
1416 type->node = node;
1417 type->type = XML_SCHEMA_TYPE_ANY;
1418 child = node->children;
1419 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1420 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1421
1422 if (IS_SCHEMA(child, "annotation")) {
1423 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1424 child = child->next;
1425 }
1426 if (child != NULL) {
1427 xmlSchemaErrorContext(ctxt, schema, node, child);
1428 if ((ctxt != NULL) && (ctxt->error != NULL))
1429 ctxt->error(ctxt->userData,
1430 "Sequence %s has unexpected content\n",
1431 type->name);
1432 }
1433
1434 return (type);
1435}
1436
1437/**
1438 * xmlSchemaParseNotation:
1439 * @ctxt: a schema validation context
1440 * @schema: the schema being built
1441 * @node: a subtree containing XML Schema informations
1442 *
1443 * parse a XML schema Notation declaration
1444 *
1445 * Returns the new structure or NULL in case of error
1446 */
1447static xmlSchemaNotationPtr
1448xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1449 xmlNodePtr node)
1450{
1451 xmlChar *name;
1452 xmlSchemaNotationPtr ret;
1453 xmlNodePtr child = NULL;
1454
1455 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1456 return (NULL);
1457 name = xmlGetProp(node, (const xmlChar *) "name");
1458 if (name == NULL) {
1459 xmlSchemaErrorContext(ctxt, schema, node, child);
1460 if ((ctxt != NULL) && (ctxt->error != NULL))
1461 ctxt->error(ctxt->userData, "Notation has no name\n");
1462 return (NULL);
1463 }
1464 ret = xmlSchemaAddNotation(ctxt, schema, name);
1465 if (ret == NULL) {
1466 xmlFree(name);
1467 return (NULL);
1468 }
1469 child = node->children;
1470 if (IS_SCHEMA(child, "annotation")) {
1471 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1472 child = child->next;
1473 }
1474 if (child != NULL) {
1475 xmlSchemaErrorContext(ctxt, schema, node, child);
1476 if ((ctxt != NULL) && (ctxt->error != NULL))
1477 ctxt->error(ctxt->userData,
1478 "notation %s has unexpected content\n",
1479 name);
1480 }
1481
1482 return (ret);
1483}
1484
1485/**
1486 * xmlSchemaParseAnyAttribute:
1487 * @ctxt: a schema validation context
1488 * @schema: the schema being built
1489 * @node: a subtree containing XML Schema informations
1490 *
1491 * parse a XML schema AnyAttrribute declaration
1492 * *WARNING* this interface is highly subject to change
1493 *
1494 * Returns an attribute def structure or NULL
1495 */
1496static xmlSchemaAttributePtr
1497xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1498 xmlNodePtr node)
1499{
1500 xmlChar *processContents;
1501 xmlSchemaAttributePtr ret;
1502 xmlNodePtr child = NULL;
1503 char name[100];
1504
1505 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1506 return (NULL);
1507
1508 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
1509 ret = xmlSchemaAddAttribute(ctxt, schema, (xmlChar *)name);
1510 if (ret == NULL) {
1511 return (NULL);
1512 }
1513 ret->id = xmlGetProp(node, (const xmlChar *) "id");
1514 processContents = xmlGetProp(node, (const xmlChar *) "processContents");
1515 if ((processContents == NULL) ||
1516 (xmlStrEqual(processContents, (const xmlChar *)"strict"))) {
1517 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1518 } else if (xmlStrEqual(processContents, (const xmlChar *)"skip")) {
1519 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1520 } else if (xmlStrEqual(processContents, (const xmlChar *)"lax")) {
1521 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
1522 } else {
1523 xmlSchemaErrorContext(ctxt, schema, node, child);
1524 if ((ctxt != NULL) && (ctxt->error != NULL))
1525 ctxt->error(ctxt->userData,
1526 "anyAttribute has unexpected content for processContents: %s\n",
1527 processContents);
1528 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1529 }
1530 if (processContents != NULL)
1531 xmlFree(processContents);
1532
1533 child = node->children;
1534 if (IS_SCHEMA(child, "annotation")) {
1535 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1536 child = child->next;
1537 }
1538 if (child != NULL) {
1539 xmlSchemaErrorContext(ctxt, schema, node, child);
1540 if ((ctxt != NULL) && (ctxt->error != NULL))
1541 ctxt->error(ctxt->userData,
1542 "anyAttribute %s has unexpected content\n",
1543 name);
1544 }
1545
1546 return (ret);
1547}
1548
1549
1550/**
1551 * xmlSchemaParseAttribute:
1552 * @ctxt: a schema validation context
1553 * @schema: the schema being built
1554 * @node: a subtree containing XML Schema informations
1555 *
1556 * parse a XML schema Attrribute declaration
1557 * *WARNING* this interface is highly subject to change
1558 *
1559 * Returns -1 in case of error, 0 if the declaration is inproper and
1560 * 1 in case of success.
1561 */
1562static xmlSchemaAttributePtr
1563xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1564 xmlNodePtr node)
1565{
1566 xmlChar *name, *refNs = NULL, *ref = NULL;
1567 xmlSchemaAttributePtr ret;
1568 xmlNodePtr child = NULL;
1569
1570 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1571 return (NULL);
1572 name = xmlGetProp(node, (const xmlChar *) "name");
1573 if (name == NULL) {
1574 char buf[100];
1575
1576 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1577 if (ref == NULL) {
1578 xmlSchemaErrorContext(ctxt, schema, node, child);
1579 if ((ctxt != NULL) && (ctxt->error != NULL))
1580 ctxt->error(ctxt->userData, "Attribute has no name nor ref\n");
1581 return (NULL);
1582 }
1583 snprintf(buf, 99, "anonattr%d", ctxt->counter++ + 1);
1584 name = xmlStrdup((xmlChar *) buf);
1585 }
1586 ret = xmlSchemaAddAttribute(ctxt, schema, name);
1587 if (ret == NULL) {
1588 xmlFree(name);
1589 if (ref != NULL)
1590 xmlFree(ref);
1591 return (NULL);
1592 }
1593 xmlFree(name);
1594 ret->ref = ref;
1595 ret->refNs = refNs;
1596 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
1597 child = node->children;
1598 if (IS_SCHEMA(child, "annotation")) {
1599 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1600 child = child->next;
1601 }
1602 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard88c58912002-04-23 07:12:20 +00001603 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001604 child = child->next;
1605 }
1606 if (child != NULL) {
1607 xmlSchemaErrorContext(ctxt, schema, node, child);
1608 if ((ctxt != NULL) && (ctxt->error != NULL))
1609 ctxt->error(ctxt->userData,
1610 "attribute %s has unexpected content\n",
1611 name);
1612 }
1613
1614 return (ret);
1615}
1616
1617/**
1618 * xmlSchemaParseAttributeGroup:
1619 * @ctxt: a schema validation context
1620 * @schema: the schema being built
1621 * @node: a subtree containing XML Schema informations
1622 *
1623 * parse a XML schema Attribute Group declaration
1624 * *WARNING* this interface is highly subject to change
1625 *
1626 * Returns the attribute group or NULL in case of error.
1627 */
1628static xmlSchemaAttributeGroupPtr
1629xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1630 xmlNodePtr node)
1631{
1632 xmlChar *name, *refNs = NULL, *ref = NULL;
1633 xmlSchemaAttributeGroupPtr ret;
1634 xmlSchemaAttributePtr last = NULL, attr;
1635 xmlNodePtr child = NULL;
1636 xmlChar *oldcontainer;
1637
1638 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1639 return (NULL);
1640 oldcontainer = ctxt->container;
1641 name = xmlGetProp(node, (const xmlChar *) "name");
1642 if (name == NULL) {
1643 char buf[100];
1644
1645 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1646 if (ref == NULL) {
1647 xmlSchemaErrorContext(ctxt, schema, node, child);
1648 if ((ctxt != NULL) && (ctxt->error != NULL))
1649 ctxt->error(ctxt->userData,
1650 "AttributeGroup has no name nor ref\n");
1651 return (NULL);
1652 }
1653 snprintf(buf, 99, "anonattrgroup%d", ctxt->counter++ + 1);
1654 name = xmlStrdup((xmlChar *) buf);
1655 }
1656 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
1657 if (ret == NULL) {
1658 xmlFree(name);
1659 if (ref != NULL)
1660 xmlFree(ref);
1661 return (NULL);
1662 }
1663 ret->ref = ref;
1664 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00001665 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard4255d502002-04-16 15:50:10 +00001666 child = node->children;
1667 ctxt->container = name;
1668 if (IS_SCHEMA(child, "annotation")) {
1669 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1670 child = child->next;
1671 }
1672 while ((IS_SCHEMA(child, "attribute")) ||
1673 (IS_SCHEMA(child, "attributeGroup"))) {
1674 attr = NULL;
1675 if (IS_SCHEMA(child, "attribute")) {
1676 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1677 } else if (IS_SCHEMA(child, "attributeGroup")) {
1678 attr = (xmlSchemaAttributePtr)
1679 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1680 }
1681 if (attr != NULL) {
1682 if (last == NULL) {
1683 ret->attributes = attr;
1684 last = attr;
1685 } else {
1686 last->next = attr;
1687 last = attr;
1688 }
1689 }
1690 child = child->next;
1691 }
1692 if (IS_SCHEMA(child, "anyAttribute")) {
1693 TODO
1694 child = child->next;
1695 }
1696 if (child != NULL) {
1697 xmlSchemaErrorContext(ctxt, schema, node, child);
1698 if ((ctxt != NULL) && (ctxt->error != NULL))
1699 ctxt->error(ctxt->userData,
1700 "attribute group %s has unexpected content\n",
1701 name);
1702 }
1703
1704 ctxt->container = oldcontainer;
1705 return (ret);
1706}
1707
1708/**
1709 * xmlSchemaParseElement:
1710 * @ctxt: a schema validation context
1711 * @schema: the schema being built
1712 * @node: a subtree containing XML Schema informations
1713 *
1714 * parse a XML schema Element declaration
1715 * *WARNING* this interface is highly subject to change
1716 *
1717 * Returns -1 in case of error, 0 if the declaration is inproper and
1718 * 1 in case of success.
1719 */
1720static xmlSchemaElementPtr
1721xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1722 xmlNodePtr node, int toplevel)
1723{
1724 xmlChar *name, *refNs = NULL, *ref = NULL, *namespace, *fixed;
1725 xmlSchemaElementPtr ret;
1726 xmlNodePtr child = NULL;
1727 xmlChar *oldcontainer;
1728
1729 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1730 return (NULL);
1731 oldcontainer = ctxt->container;
1732 name = xmlGetProp(node, (const xmlChar *) "name");
1733 if (name == NULL) {
1734 char buf[100];
1735
1736 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1737 if (ref == NULL) {
1738 xmlSchemaErrorContext(ctxt, schema, node, child);
1739 if ((ctxt != NULL) && (ctxt->error != NULL))
1740 ctxt->error(ctxt->userData, "Element has no name nor ref\n");
1741 return (NULL);
1742 }
1743 snprintf(buf, 99, "anonelem%d", ctxt->counter++ + 1);
1744 name = xmlStrdup((xmlChar *) buf);
1745 }
1746 namespace = xmlGetProp(node, (const xmlChar *) "targetNamespace");
1747 if (namespace == NULL)
1748 ret =
1749 xmlSchemaAddElement(ctxt, schema, name,
1750 schema->targetNamespace);
1751 else
1752 ret = xmlSchemaAddElement(ctxt, schema, name, namespace);
1753 if (namespace != NULL)
1754 xmlFree(namespace);
1755 if (ret == NULL) {
1756 xmlFree(name);
1757 if (ref != NULL)
1758 xmlFree(ref);
1759 return (NULL);
1760 }
1761 ret->type = XML_SCHEMA_TYPE_ELEMENT;
1762 ret->ref = ref;
1763 ret->refNs = refNs;
1764 if (ref != NULL)
1765 ret->flags |= XML_SCHEMAS_ELEM_REF;
1766 if (toplevel)
1767 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
1768 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
1769 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1770 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
1771 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1772 ctxt->container = name;
1773
1774 ret->id = xmlGetProp(node, BAD_CAST "id");
1775 ret->namedType = xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
1776 ret->substGroup = xmlGetQNameProp(ctxt, node, "substitutionGroup",
1777 &(ret->substGroupNs));
1778 fixed = xmlGetProp(node, BAD_CAST "fixed");
1779 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
1780 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1781
1782 ret->value = xmlGetProp(node, BAD_CAST "default");
1783 if ((ret->value != NULL) && (fixed != NULL)) {
1784 xmlSchemaErrorContext(ctxt, schema, node, child);
1785 ctxt->error(ctxt->userData,
1786 "Element %s has both default and fixed\n",
1787 ret->name);
1788 xmlFree(fixed);
1789 } else if (fixed != NULL) {
1790 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
1791 ret->value = fixed;
1792 }
1793
1794 child = node->children;
1795 if (IS_SCHEMA(child, "annotation")) {
1796 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1797 child = child->next;
1798 }
1799 if (IS_SCHEMA(child, "complexType")) {
1800 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
1801 child = child->next;
1802 } else if (IS_SCHEMA(child, "simpleType")) {
1803 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1804 child = child->next;
1805 }
1806 while ((IS_SCHEMA(child, "unique")) ||
1807 (IS_SCHEMA(child, "key")) ||
1808 (IS_SCHEMA(child, "keyref"))) {
1809 TODO
1810 child = child->next;
1811 }
1812 if (child != NULL) {
1813 xmlSchemaErrorContext(ctxt, schema, node, child);
1814 if ((ctxt != NULL) && (ctxt->error != NULL))
1815 ctxt->error(ctxt->userData,
1816 "element %s has unexpected content\n",
1817 name);
1818 }
1819
1820 ctxt->container = oldcontainer;
1821 xmlFree(name);
1822 return (ret);
1823}
1824
1825/**
1826 * xmlSchemaParseUnion:
1827 * @ctxt: a schema validation context
1828 * @schema: the schema being built
1829 * @node: a subtree containing XML Schema informations
1830 *
1831 * parse a XML schema Union definition
1832 * *WARNING* this interface is highly subject to change
1833 *
1834 * Returns -1 in case of error, 0 if the declaration is inproper and
1835 * 1 in case of success.
1836 */
1837static xmlSchemaTypePtr
1838xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1839 xmlNodePtr node)
1840{
1841 xmlSchemaTypePtr type, subtype, last = NULL;
1842 xmlNodePtr child = NULL;
1843 xmlChar name[30];
1844
1845 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1846 return (NULL);
1847
1848
1849 snprintf((char *)name, 30, "union %d", ctxt->counter++ + 1);
1850 type = xmlSchemaAddType(ctxt, schema, name);
1851 if (type == NULL)
1852 return (NULL);
1853 type->node = node;
1854 type->type = XML_SCHEMA_TYPE_LIST;
1855 type->id = xmlGetProp(node, BAD_CAST "id");
1856 type->ref = xmlGetProp(node, BAD_CAST "memberTypes");
1857
1858 child = node->children;
1859 if (IS_SCHEMA(child, "annotation")) {
1860 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1861 child = child->next;
1862 }
1863 while (IS_SCHEMA(child, "simpleType")) {
1864 subtype = (xmlSchemaTypePtr)
1865 xmlSchemaParseSimpleType(ctxt, schema, child);
1866 if (subtype != NULL) {
1867 if (last == NULL) {
1868 type->subtypes = subtype;
1869 last = subtype;
1870 } else {
1871 last->next = subtype;
1872 last = subtype;
1873 }
1874 last->next = NULL;
1875 }
1876 child = child->next;
1877 }
1878 if (child != NULL) {
1879 xmlSchemaErrorContext(ctxt, schema, node, child);
1880 if ((ctxt != NULL) && (ctxt->error != NULL))
1881 ctxt->error(ctxt->userData,
1882 "Union %s has unexpected content\n",
1883 type->name);
1884 }
1885 return (type);
1886}
1887
1888/**
1889 * xmlSchemaParseList:
1890 * @ctxt: a schema validation context
1891 * @schema: the schema being built
1892 * @node: a subtree containing XML Schema informations
1893 *
1894 * parse a XML schema List definition
1895 * *WARNING* this interface is highly subject to change
1896 *
1897 * Returns -1 in case of error, 0 if the declaration is inproper and
1898 * 1 in case of success.
1899 */
1900static xmlSchemaTypePtr
1901xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1902 xmlNodePtr node)
1903{
1904 xmlSchemaTypePtr type, subtype;
1905 xmlNodePtr child = NULL;
1906 xmlChar name[30];
1907
1908 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1909 return (NULL);
1910
1911 snprintf((char *)name, 30, "list %d", ctxt->counter++ + 1);
1912 type = xmlSchemaAddType(ctxt, schema, name);
1913 if (type == NULL)
1914 return (NULL);
1915 type->node = node;
1916 type->type = XML_SCHEMA_TYPE_LIST;
1917 type->id = xmlGetProp(node, BAD_CAST "id");
1918 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
1919
1920 child = node->children;
1921 if (IS_SCHEMA(child, "annotation")) {
1922 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1923 child = child->next;
1924 }
1925 subtype = NULL;
1926 if (IS_SCHEMA(child, "simpleType")) {
1927 subtype = (xmlSchemaTypePtr)
1928 xmlSchemaParseSimpleType(ctxt, schema, child);
1929 child = child->next;
1930 type->subtypes = subtype;
1931 }
1932 if (child != NULL) {
1933 xmlSchemaErrorContext(ctxt, schema, node, child);
1934 if ((ctxt != NULL) && (ctxt->error != NULL))
1935 ctxt->error(ctxt->userData,
1936 "List %s has unexpected content\n",
1937 type->name);
1938 }
1939 return (type);
1940}
1941/**
1942 * xmlSchemaParseSimpleType:
1943 * @ctxt: a schema validation context
1944 * @schema: the schema being built
1945 * @node: a subtree containing XML Schema informations
1946 *
1947 * parse a XML schema Simple Type definition
1948 * *WARNING* this interface is highly subject to change
1949 *
1950 * Returns -1 in case of error, 0 if the declaration is inproper and
1951 * 1 in case of success.
1952 */
1953static xmlSchemaTypePtr
1954xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1955 xmlNodePtr node)
1956{
1957 xmlSchemaTypePtr type, subtype;
1958 xmlNodePtr child = NULL;
1959 xmlChar *name;
1960
1961 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1962 return (NULL);
1963
1964
1965 name = xmlGetProp(node, (const xmlChar *) "name");
1966 if (name == NULL) {
1967 char buf[100];
1968
1969 snprintf(buf, 99, "simpletype%d", ctxt->counter++ + 1);
1970 name = xmlStrdup((xmlChar *) buf);
1971 }
1972 if (name == NULL) {
1973 xmlSchemaErrorContext(ctxt, schema, node, child);
1974 if ((ctxt != NULL) && (ctxt->error != NULL))
1975 ctxt->error(ctxt->userData, "simpleType has no name\n");
1976 return (NULL);
1977 }
1978 type = xmlSchemaAddType(ctxt, schema, name);
1979 xmlFree(name);
1980 if (type == NULL)
1981 return (NULL);
1982 type->node = node;
1983 type->type = XML_SCHEMA_TYPE_SIMPLE;
1984 type->id = xmlGetProp(node, BAD_CAST "id");
1985
1986 child = node->children;
1987 if (IS_SCHEMA(child, "annotation")) {
1988 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1989 child = child->next;
1990 }
1991 subtype = NULL;
1992 if (IS_SCHEMA(child, "restriction")) {
1993 subtype = (xmlSchemaTypePtr)
1994 xmlSchemaParseRestriction(ctxt, schema, child, 1);
1995 child = child->next;
1996 } else if (IS_SCHEMA(child, "list")) {
1997 subtype = (xmlSchemaTypePtr)
1998 xmlSchemaParseList(ctxt, schema, child);
1999 child = child->next;
2000 } else if (IS_SCHEMA(child, "union")) {
2001 subtype = (xmlSchemaTypePtr)
2002 xmlSchemaParseUnion(ctxt, schema, child);
2003 child = child->next;
2004 }
2005 type->subtypes = subtype;
2006 if (child != NULL) {
2007 xmlSchemaErrorContext(ctxt, schema, node, child);
2008 if ((ctxt != NULL) && (ctxt->error != NULL))
2009 ctxt->error(ctxt->userData,
2010 "SimpleType %s has unexpected content\n",
2011 type->name);
2012 }
2013
2014 return (type);
2015}
2016
2017
2018/**
2019 * xmlSchemaParseGroup:
2020 * @ctxt: a schema validation context
2021 * @schema: the schema being built
2022 * @node: a subtree containing XML Schema informations
2023 *
2024 * parse a XML schema Group definition
2025 * *WARNING* this interface is highly subject to change
2026 *
2027 * Returns -1 in case of error, 0 if the declaration is inproper and
2028 * 1 in case of success.
2029 */
2030static xmlSchemaTypePtr
2031xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2032 xmlNodePtr node)
2033{
2034 xmlSchemaTypePtr type, subtype;
2035 xmlNodePtr child = NULL;
2036 xmlChar *name, *ref = NULL, *refNs = NULL;
2037
2038 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2039 return (NULL);
2040
2041
2042 name = xmlGetProp(node, (const xmlChar *) "name");
2043 if (name == NULL) {
2044 char buf[100];
2045
2046 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2047 if (ref == NULL) {
2048 xmlSchemaErrorContext(ctxt, schema, node, child);
2049 if ((ctxt != NULL) && (ctxt->error != NULL))
2050 ctxt->error(ctxt->userData, "Group has no name nor ref\n");
2051 return (NULL);
2052 }
2053 snprintf(buf, 99, "anongroup%d", ctxt->counter++ + 1);
2054 name = xmlStrdup((xmlChar *) buf);
2055 }
2056 type = xmlSchemaAddType(ctxt, schema, name);
2057 if (type == NULL)
2058 return (NULL);
2059 type->node = node;
2060 type->type = XML_SCHEMA_TYPE_GROUP;
2061 type->id = xmlGetProp(node, BAD_CAST "id");
2062 type->ref = ref;
2063 type->refNs = refNs;
2064 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2065 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2066
2067 child = node->children;
2068 if (IS_SCHEMA(child, "annotation")) {
2069 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2070 child = child->next;
2071 }
2072 subtype = NULL;
2073 if (IS_SCHEMA(child, "all")) {
2074 subtype = (xmlSchemaTypePtr)
2075 xmlSchemaParseAll(ctxt, schema, child);
2076 child = child->next;
2077 } else if (IS_SCHEMA(child, "choice")) {
2078 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2079 child = child->next;
2080 } else if (IS_SCHEMA(child, "sequence")) {
2081 subtype = (xmlSchemaTypePtr)
2082 xmlSchemaParseSequence(ctxt, schema, child);
2083 child = child->next;
2084 }
2085 if (subtype != NULL)
2086 type->subtypes = subtype;
2087 if (child != NULL) {
2088 xmlSchemaErrorContext(ctxt, schema, node, child);
2089 if ((ctxt != NULL) && (ctxt->error != NULL))
2090 ctxt->error(ctxt->userData,
2091 "Group %s has unexpected content\n",
2092 type->name);
2093 }
2094
2095 return (type);
2096}
2097
2098/**
2099 * xmlSchemaParseAll:
2100 * @ctxt: a schema validation context
2101 * @schema: the schema being built
2102 * @node: a subtree containing XML Schema informations
2103 *
2104 * parse a XML schema All definition
2105 * *WARNING* this interface is highly subject to change
2106 *
2107 * Returns -1 in case of error, 0 if the declaration is inproper and
2108 * 1 in case of success.
2109 */
2110static xmlSchemaTypePtr
2111xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2112 xmlNodePtr node)
2113{
2114 xmlSchemaTypePtr type, subtype, last = NULL;
2115 xmlNodePtr child = NULL;
2116 xmlChar name[30];
2117
2118 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2119 return (NULL);
2120
2121
2122 snprintf((char *)name, 30, "all%d", ctxt->counter++ + 1);
2123 type = xmlSchemaAddType(ctxt, schema, name);
2124 if (type == NULL)
2125 return (NULL);
2126 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002127 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002128 type->id = xmlGetProp(node, BAD_CAST "id");
2129 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2130 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2131
2132 child = node->children;
2133 if (IS_SCHEMA(child, "annotation")) {
2134 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2135 child = child->next;
2136 }
2137 while (IS_SCHEMA(child, "element")) {
2138 subtype = (xmlSchemaTypePtr)
2139 xmlSchemaParseElement(ctxt, schema, child, 0);
2140 if (subtype != NULL) {
2141 if (last == NULL) {
2142 type->subtypes = subtype;
2143 last = subtype;
2144 } else {
2145 last->next = subtype;
2146 last = subtype;
2147 }
2148 last->next = NULL;
2149 }
2150 child = child->next;
2151 }
2152 if (child != NULL) {
2153 xmlSchemaErrorContext(ctxt, schema, node, child);
2154 if ((ctxt != NULL) && (ctxt->error != NULL))
2155 ctxt->error(ctxt->userData,
2156 "All %s has unexpected content\n",
2157 type->name);
2158 }
2159
2160 return (type);
2161}
2162
2163/**
2164 * xmlSchemaParseChoice:
2165 * @ctxt: a schema validation context
2166 * @schema: the schema being built
2167 * @node: a subtree containing XML Schema informations
2168 *
2169 * parse a XML schema Choice definition
2170 * *WARNING* this interface is highly subject to change
2171 *
2172 * Returns -1 in case of error, 0 if the declaration is inproper and
2173 * 1 in case of success.
2174 */
2175static xmlSchemaTypePtr
2176xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2177 xmlNodePtr node)
2178{
2179 xmlSchemaTypePtr type, subtype, last = NULL;
2180 xmlNodePtr child = NULL;
2181 xmlChar name[30];
2182
2183 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2184 return (NULL);
2185
2186
2187 snprintf((char *)name, 30, "choice %d", ctxt->counter++ + 1);
2188 type = xmlSchemaAddType(ctxt, schema, name);
2189 if (type == NULL)
2190 return (NULL);
2191 type->node = node;
2192 type->type = XML_SCHEMA_TYPE_CHOICE;
2193 type->id = xmlGetProp(node, BAD_CAST "id");
2194 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2195 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2196
2197 child = node->children;
2198 if (IS_SCHEMA(child, "annotation")) {
2199 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2200 child = child->next;
2201 }
2202 while ((IS_SCHEMA(child, "element")) ||
2203 (IS_SCHEMA(child, "group")) ||
2204 (IS_SCHEMA(child, "any")) ||
2205 (IS_SCHEMA(child, "choice")) ||
2206 (IS_SCHEMA(child, "sequence"))) {
2207 subtype = NULL;
2208 if (IS_SCHEMA(child, "element")) {
2209 subtype = (xmlSchemaTypePtr)
2210 xmlSchemaParseElement(ctxt, schema, child, 0);
2211 } else if (IS_SCHEMA(child, "group")) {
2212 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2213 } else if (IS_SCHEMA(child, "any")) {
2214 subtype = xmlSchemaParseAny(ctxt, schema, child);
2215 } else if (IS_SCHEMA(child, "sequence")) {
2216 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2217 } else if (IS_SCHEMA(child, "choice")) {
2218 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2219 }
2220 if (subtype != NULL) {
2221 if (last == NULL) {
2222 type->subtypes = subtype;
2223 last = subtype;
2224 } else {
2225 last->next = subtype;
2226 last = subtype;
2227 }
2228 last->next = NULL;
2229 }
2230 child = child->next;
2231 }
2232 if (child != NULL) {
2233 xmlSchemaErrorContext(ctxt, schema, node, child);
2234 if ((ctxt != NULL) && (ctxt->error != NULL))
2235 ctxt->error(ctxt->userData,
2236 "Choice %s has unexpected content\n",
2237 type->name);
2238 }
2239
2240 return (type);
2241}
2242
2243/**
2244 * xmlSchemaParseSequence:
2245 * @ctxt: a schema validation context
2246 * @schema: the schema being built
2247 * @node: a subtree containing XML Schema informations
2248 *
2249 * parse a XML schema Sequence definition
2250 * *WARNING* this interface is highly subject to change
2251 *
2252 * Returns -1 in case of error, 0 if the declaration is inproper and
2253 * 1 in case of success.
2254 */
2255static xmlSchemaTypePtr
2256xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2257 xmlNodePtr node)
2258{
2259 xmlSchemaTypePtr type, subtype, last = NULL;
2260 xmlNodePtr child = NULL;
2261 xmlChar name[30];
2262
2263 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2264 return (NULL);
2265
2266
2267 snprintf((char *)name, 30, "sequence %d", ctxt->counter++ + 1);
2268 type = xmlSchemaAddType(ctxt, schema, name);
2269 if (type == NULL)
2270 return (NULL);
2271 type->node = node;
2272 type->type = XML_SCHEMA_TYPE_SEQUENCE;
2273 type->id = xmlGetProp(node, BAD_CAST "id");
2274 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2275 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2276
2277 child = node->children;
2278 if (IS_SCHEMA(child, "annotation")) {
2279 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2280 child = child->next;
2281 }
2282 while ((IS_SCHEMA(child, "element")) ||
2283 (IS_SCHEMA(child, "group")) ||
2284 (IS_SCHEMA(child, "any")) ||
2285 (IS_SCHEMA(child, "choice")) ||
2286 (IS_SCHEMA(child, "sequence"))) {
2287 subtype = NULL;
2288 if (IS_SCHEMA(child, "element")) {
2289 subtype = (xmlSchemaTypePtr)
2290 xmlSchemaParseElement(ctxt, schema, child, 0);
2291 } else if (IS_SCHEMA(child, "group")) {
2292 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2293 } else if (IS_SCHEMA(child, "any")) {
2294 subtype = xmlSchemaParseAny(ctxt, schema, child);
2295 } else if (IS_SCHEMA(child, "choice")) {
2296 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2297 } else if (IS_SCHEMA(child, "sequence")) {
2298 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2299 }
2300 if (subtype != NULL) {
2301 if (last == NULL) {
2302 type->subtypes = subtype;
2303 last = subtype;
2304 } else {
2305 last->next = subtype;
2306 last = subtype;
2307 }
2308 last->next = NULL;
2309 }
2310 child = child->next;
2311 }
2312 if (child != NULL) {
2313 xmlSchemaErrorContext(ctxt, schema, node, child);
2314 if ((ctxt != NULL) && (ctxt->error != NULL))
2315 ctxt->error(ctxt->userData,
2316 "Sequence %s has unexpected content\n",
2317 type->name);
2318 }
2319
2320 return (type);
2321}
2322
2323/**
2324 * xmlSchemaParseRestriction:
2325 * @ctxt: a schema validation context
2326 * @schema: the schema being built
2327 * @node: a subtree containing XML Schema informations
2328 * @simple: is that part of a simple type.
2329 *
2330 * parse a XML schema Restriction definition
2331 * *WARNING* this interface is highly subject to change
2332 *
2333 * Returns the type definition or NULL in case of error
2334 */
2335static xmlSchemaTypePtr
2336xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2337 xmlNodePtr node, int simple)
2338{
2339 xmlSchemaTypePtr type, subtype;
2340 xmlSchemaFacetPtr facet, lastfacet = NULL;
2341 xmlNodePtr child = NULL;
2342 xmlChar name[30];
2343 xmlChar *oldcontainer;
2344
2345 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2346 return (NULL);
2347
2348 oldcontainer = ctxt->container;
2349
2350 snprintf((char *)name, 30, "restriction %d", ctxt->counter++ + 1);
2351 type = xmlSchemaAddType(ctxt, schema, name);
2352 if (type == NULL)
2353 return (NULL);
2354 type->node = node;
2355 type->type = XML_SCHEMA_TYPE_RESTRICTION;
2356 type->id = xmlGetProp(node, BAD_CAST "id");
2357 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2358 if ((!simple) && (type->base == NULL)) {
2359 xmlSchemaErrorContext(ctxt, schema, node, child);
2360 if ((ctxt != NULL) && (ctxt->error != NULL))
2361 ctxt->error(ctxt->userData,
2362 "Restriction %s has no base\n",
2363 type->name);
2364 }
2365 ctxt->container = name;
2366
2367 child = node->children;
2368 if (IS_SCHEMA(child, "annotation")) {
2369 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2370 child = child->next;
2371 }
2372 subtype = NULL;
2373
2374 if (IS_SCHEMA(child, "all")) {
2375 subtype = (xmlSchemaTypePtr)
2376 xmlSchemaParseAll(ctxt, schema, child);
2377 child = child->next;
2378 type->subtypes = subtype;
2379 } else if (IS_SCHEMA(child, "choice")) {
2380 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2381 child = child->next;
2382 type->subtypes = subtype;
2383 } else if (IS_SCHEMA(child, "sequence")) {
2384 subtype = (xmlSchemaTypePtr)
2385 xmlSchemaParseSequence(ctxt, schema, child);
2386 child = child->next;
2387 type->subtypes = subtype;
2388 } else if (IS_SCHEMA(child, "group")) {
2389 subtype = (xmlSchemaTypePtr)
2390 xmlSchemaParseGroup(ctxt, schema, child);
2391 child = child->next;
2392 type->subtypes = subtype;
2393 } else {
2394 if (IS_SCHEMA(child, "simpleType")) {
2395 subtype = (xmlSchemaTypePtr)
2396 xmlSchemaParseSimpleType(ctxt, schema, child);
2397 child = child->next;
2398 type->baseType = subtype;
2399 }
2400 /*
2401 * Facets
2402 */
2403 while ((IS_SCHEMA(child, "minInclusive")) ||
2404 (IS_SCHEMA(child, "minExclusive")) ||
2405 (IS_SCHEMA(child, "maxInclusive")) ||
2406 (IS_SCHEMA(child, "maxExclusive")) ||
2407 (IS_SCHEMA(child, "totalDigits")) ||
2408 (IS_SCHEMA(child, "fractionDigits")) ||
2409 (IS_SCHEMA(child, "pattern")) ||
2410 (IS_SCHEMA(child, "enumeration")) ||
2411 (IS_SCHEMA(child, "whiteSpace")) ||
2412 (IS_SCHEMA(child, "length")) ||
2413 (IS_SCHEMA(child, "maxLength")) ||
2414 (IS_SCHEMA(child, "minLength"))) {
2415 facet = xmlSchemaParseFacet(ctxt, schema, child);
2416 if (facet != NULL) {
2417 if (lastfacet == NULL) {
2418 type->facets = facet;
2419 lastfacet = facet;
2420 } else {
2421 lastfacet->next = facet;
2422 lastfacet = facet;
2423 }
2424 lastfacet->next = NULL;
2425 }
2426 child = child->next;
2427 }
2428 }
2429 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2430 if (child != NULL) {
2431 xmlSchemaErrorContext(ctxt, schema, node, child);
2432 if ((ctxt != NULL) && (ctxt->error != NULL))
2433 ctxt->error(ctxt->userData,
2434 "Restriction %s has unexpected content\n",
2435 type->name);
2436 }
2437 ctxt->container = oldcontainer;
2438 return (type);
2439}
2440
2441/**
2442 * xmlSchemaParseExtension:
2443 * @ctxt: a schema validation context
2444 * @schema: the schema being built
2445 * @node: a subtree containing XML Schema informations
2446 *
2447 * parse a XML schema Extension definition
2448 * *WARNING* this interface is highly subject to change
2449 *
2450 * Returns the type definition or NULL in case of error
2451 */
2452static xmlSchemaTypePtr
2453xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2454 xmlNodePtr node)
2455{
2456 xmlSchemaTypePtr type, subtype;
2457 xmlNodePtr child = NULL;
2458 xmlChar name[30];
2459 xmlChar *oldcontainer;
2460
2461 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2462 return (NULL);
2463
2464 oldcontainer = ctxt->container;
2465
2466 snprintf((char *)name, 30, "extension %d", ctxt->counter++ + 1);
2467 type = xmlSchemaAddType(ctxt, schema, name);
2468 if (type == NULL)
2469 return (NULL);
2470 type->node = node;
2471 type->type = XML_SCHEMA_TYPE_EXTENSION;
2472 type->id = xmlGetProp(node, BAD_CAST "id");
2473 ctxt->container = name;
2474
2475 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2476 if (type->base == NULL) {
2477 xmlSchemaErrorContext(ctxt, schema, node, child);
2478 if ((ctxt != NULL) && (ctxt->error != NULL))
2479 ctxt->error(ctxt->userData,
2480 "Extension %s has no base\n",
2481 type->name);
2482 }
2483 child = node->children;
2484 if (IS_SCHEMA(child, "annotation")) {
2485 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2486 child = child->next;
2487 }
2488 subtype = NULL;
2489
2490 if (IS_SCHEMA(child, "all")) {
2491 subtype = xmlSchemaParseAll(ctxt, schema, child);
2492 child = child->next;
2493 } else if (IS_SCHEMA(child, "choice")) {
2494 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2495 child = child->next;
2496 } else if (IS_SCHEMA(child, "sequence")) {
2497 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2498 child = child->next;
2499 } else if (IS_SCHEMA(child, "group")) {
2500 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2501 child = child->next;
2502 }
2503 if (subtype != NULL)
2504 type->subtypes = subtype;
2505 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2506 if (child != NULL) {
2507 xmlSchemaErrorContext(ctxt, schema, node, child);
2508 if ((ctxt != NULL) && (ctxt->error != NULL))
2509 ctxt->error(ctxt->userData,
2510 "Extension %s has unexpected content\n",
2511 type->name);
2512 }
2513 ctxt->container = oldcontainer;
2514 return (type);
2515}
2516
2517/**
2518 * xmlSchemaParseSimpleContent:
2519 * @ctxt: a schema validation context
2520 * @schema: the schema being built
2521 * @node: a subtree containing XML Schema informations
2522 *
2523 * parse a XML schema SimpleContent definition
2524 * *WARNING* this interface is highly subject to change
2525 *
2526 * Returns the type definition or NULL in case of error
2527 */
2528static xmlSchemaTypePtr
2529xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2530 xmlNodePtr node)
2531{
2532 xmlSchemaTypePtr type, subtype;
2533 xmlNodePtr child = NULL;
2534 xmlChar name[30];
2535
2536 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2537 return (NULL);
2538
2539
2540 snprintf((char *)name, 30, "complexContent %d", ctxt->counter++ + 1);
2541 type = xmlSchemaAddType(ctxt, schema, name);
2542 if (type == NULL)
2543 return (NULL);
2544 type->node = node;
2545 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
2546 type->id = xmlGetProp(node, BAD_CAST "id");
2547
2548 child = node->children;
2549 if (IS_SCHEMA(child, "annotation")) {
2550 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2551 child = child->next;
2552 }
2553 subtype = NULL;
2554 if (IS_SCHEMA(child, "restriction")) {
2555 subtype = (xmlSchemaTypePtr)
2556 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2557 child = child->next;
2558 } else if (IS_SCHEMA(child, "extension")) {
2559 subtype = (xmlSchemaTypePtr)
2560 xmlSchemaParseExtension(ctxt, schema, child);
2561 child = child->next;
2562 }
2563 type->subtypes = subtype;
2564 if (child != NULL) {
2565 xmlSchemaErrorContext(ctxt, schema, node, child);
2566 if ((ctxt != NULL) && (ctxt->error != NULL))
2567 ctxt->error(ctxt->userData,
2568 "SimpleContent %s has unexpected content\n",
2569 type->name);
2570 }
2571 return (type);
2572}
2573
2574/**
2575 * xmlSchemaParseComplexContent:
2576 * @ctxt: a schema validation context
2577 * @schema: the schema being built
2578 * @node: a subtree containing XML Schema informations
2579 *
2580 * parse a XML schema ComplexContent definition
2581 * *WARNING* this interface is highly subject to change
2582 *
2583 * Returns the type definition or NULL in case of error
2584 */
2585static xmlSchemaTypePtr
2586xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2587 xmlNodePtr node)
2588{
2589 xmlSchemaTypePtr type, subtype;
2590 xmlNodePtr child = NULL;
2591 xmlChar name[30];
2592
2593 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2594 return (NULL);
2595
2596
2597 snprintf((char *)name, 30, "complexContent %d", ctxt->counter++ + 1);
2598 type = xmlSchemaAddType(ctxt, schema, name);
2599 if (type == NULL)
2600 return (NULL);
2601 type->node = node;
2602 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
2603 type->id = xmlGetProp(node, BAD_CAST "id");
2604
2605 child = node->children;
2606 if (IS_SCHEMA(child, "annotation")) {
2607 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2608 child = child->next;
2609 }
2610 subtype = NULL;
2611 if (IS_SCHEMA(child, "restriction")) {
2612 subtype = (xmlSchemaTypePtr)
2613 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2614 child = child->next;
2615 } else if (IS_SCHEMA(child, "extension")) {
2616 subtype = (xmlSchemaTypePtr)
2617 xmlSchemaParseExtension(ctxt, schema, child);
2618 child = child->next;
2619 }
2620 type->subtypes = subtype;
2621 if (child != NULL) {
2622 xmlSchemaErrorContext(ctxt, schema, node, child);
2623 if ((ctxt != NULL) && (ctxt->error != NULL))
2624 ctxt->error(ctxt->userData,
2625 "ComplexContent %s has unexpected content\n",
2626 type->name);
2627 }
2628 return (type);
2629}
2630
2631/**
2632 * xmlSchemaParseComplexType:
2633 * @ctxt: a schema validation context
2634 * @schema: the schema being built
2635 * @node: a subtree containing XML Schema informations
2636 *
2637 * parse a XML schema Complex Type definition
2638 * *WARNING* this interface is highly subject to change
2639 *
2640 * Returns the type definition or NULL in case of error
2641 */
2642static xmlSchemaTypePtr
2643xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2644 xmlNodePtr node)
2645{
2646 xmlSchemaTypePtr type, subtype;
2647 xmlNodePtr child = NULL;
2648 xmlChar *name;
2649 xmlChar *oldcontainer;
2650
2651 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2652 return (NULL);
2653
2654 oldcontainer = ctxt->container;
2655 name = xmlGetProp(node, (const xmlChar *) "name");
2656 if (name == NULL) {
2657 char buf[100];
2658
2659 snprintf(buf, 99, "anontype%d", ctxt->counter++ + 1);
2660 name = xmlStrdup((xmlChar *) buf);
2661 }
2662 if (name == NULL) {
2663 xmlSchemaErrorContext(ctxt, schema, node, child);
2664 if ((ctxt != NULL) && (ctxt->error != NULL))
2665 ctxt->error(ctxt->userData, "complexType has no name\n");
2666 return (NULL);
2667 }
2668 type = xmlSchemaAddType(ctxt, schema, name);
2669 if (type == NULL) {
2670 xmlFree(name);
2671 return (NULL);
2672 }
2673 type->node = node;
2674 type->type = XML_SCHEMA_TYPE_COMPLEX;
2675 type->id = xmlGetProp(node, BAD_CAST "id");
2676 ctxt->container = name;
2677
2678 child = node->children;
2679 if (IS_SCHEMA(child, "annotation")) {
2680 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2681 child = child->next;
2682 }
2683 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillarddecd64d2002-04-18 14:41:51 +00002684 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002685 child = child->next;
2686 } else if (IS_SCHEMA(child, "complexContent")) {
2687 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
2688 child = child->next;
2689 } else {
2690 subtype = NULL;
2691
2692 if (IS_SCHEMA(child, "all")) {
2693 subtype = xmlSchemaParseAll(ctxt, schema, child);
2694 child = child->next;
2695 } else if (IS_SCHEMA(child, "choice")) {
2696 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2697 child = child->next;
2698 } else if (IS_SCHEMA(child, "sequence")) {
2699 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2700 child = child->next;
2701 } else if (IS_SCHEMA(child, "group")) {
2702 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2703 child = child->next;
2704 }
2705 if (subtype != NULL)
2706 type->subtypes = subtype;
2707 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2708 }
2709 if (child != NULL) {
2710 xmlSchemaErrorContext(ctxt, schema, node, child);
2711 if ((ctxt != NULL) && (ctxt->error != NULL))
2712 ctxt->error(ctxt->userData,
2713 "ComplexType %s has unexpected content\n",
2714 type->name);
2715 }
2716 ctxt->container = oldcontainer;
2717 xmlFree(name);
2718 return (type);
2719}
2720
2721
2722/**
2723 * xmlSchemaParseSchema:
2724 * @ctxt: a schema validation context
2725 * @node: a subtree containing XML Schema informations
2726 *
2727 * parse a XML schema definition from a node set
2728 * *WARNING* this interface is highly subject to change
2729 *
2730 * Returns the internal XML Schema structure built from the resource or
2731 * NULL in case of error
2732 */
2733static xmlSchemaPtr
2734xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2735{
2736 xmlSchemaPtr schema = NULL;
2737 xmlSchemaAnnotPtr annot;
2738 xmlNodePtr child = NULL;
2739 xmlChar *val;
2740
2741 if ((ctxt == NULL) || (node == NULL))
2742 return (NULL);
2743
2744 if (IS_SCHEMA(node, "schema")) {
2745 schema = xmlSchemaNewSchema(ctxt);
2746 if (schema == NULL)
2747 return(NULL);
2748 schema->targetNamespace = xmlGetProp(node, BAD_CAST "targetNamespace");
2749 schema->id = xmlGetProp(node, BAD_CAST "id");
2750 schema->version = xmlGetProp(node, BAD_CAST "version");
2751 val = xmlGetProp(node, BAD_CAST "elementFormDefault");
2752 if (val != NULL) {
2753 if (xmlStrEqual(val, BAD_CAST "qualified"))
2754 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
2755 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
2756 xmlSchemaErrorContext(ctxt, schema, node, child);
2757 if ((ctxt != NULL) && (ctxt->error != NULL)) {
2758 ctxt->error(ctxt->userData,
2759 "Invalid value %s for elementFormDefault\n",
2760 val);
2761 }
2762 }
2763 xmlFree(val);
2764 }
2765 val = xmlGetProp(node, BAD_CAST "attributeFormDefault");
2766 if (val != NULL) {
2767 if (xmlStrEqual(val, BAD_CAST "qualified"))
2768 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
2769 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
2770 xmlSchemaErrorContext(ctxt, schema, node, child);
2771 if ((ctxt != NULL) && (ctxt->error != NULL)) {
2772 ctxt->error(ctxt->userData,
2773 "Invalid value %s for elementFormDefault\n",
2774 val);
2775 }
2776 }
2777 xmlFree(val);
2778 }
2779
2780 child = node->children;
2781 while ((IS_SCHEMA(child, "include")) ||
2782 (IS_SCHEMA(child, "import")) ||
2783 (IS_SCHEMA(child, "redefine")) ||
2784 (IS_SCHEMA(child, "annotation"))) {
2785 if (IS_SCHEMA(child, "annotation")) {
2786 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2787 if (schema->annot == NULL)
2788 schema->annot = annot;
2789 else
2790 xmlSchemaFreeAnnot(annot);
2791 } else if (IS_SCHEMA(child, "include")) {
2792 TODO
2793 } else if (IS_SCHEMA(child, "import")) {
2794 TODO
2795 } else if (IS_SCHEMA(child, "redefine")) {
2796 TODO
2797 }
2798 child = child->next;
2799 }
2800 while (child != NULL) {
2801 if (IS_SCHEMA(child, "complexType")) {
2802 xmlSchemaParseComplexType(ctxt, schema, child);
2803 child = child->next;
2804 } else if (IS_SCHEMA(child, "simpleType")) {
2805 xmlSchemaParseSimpleType(ctxt, schema, child);
2806 child = child->next;
2807 } else if (IS_SCHEMA(child, "element")) {
2808 xmlSchemaParseElement(ctxt, schema, child, 1);
2809 child = child->next;
2810 } else if (IS_SCHEMA(child, "attribute")) {
2811 xmlSchemaParseAttribute(ctxt, schema, child);
2812 child = child->next;
2813 } else if (IS_SCHEMA(child, "attributeGroup")) {
2814 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2815 child = child->next;
2816 } else if (IS_SCHEMA(child, "group")) {
2817 xmlSchemaParseGroup(ctxt, schema, child);
2818 child = child->next;
2819 } else if (IS_SCHEMA(child, "notation")) {
2820 xmlSchemaParseNotation(ctxt, schema, child);
2821 child = child->next;
2822 } else {
2823 xmlSchemaErrorContext(ctxt, schema, node, child);
2824 if ((ctxt != NULL) && (ctxt->error != NULL))
2825 ctxt->error(ctxt->userData,
2826 "Schemas: unexpected element %s here \n",
2827 child->name);
2828 child = child->next;
2829 }
2830 while (IS_SCHEMA(child, "annotation")) {
2831 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2832 if (schema->annot == NULL)
2833 schema->annot = annot;
2834 else
2835 xmlSchemaFreeAnnot(annot);
2836 child = child->next;
2837 }
2838 }
2839 }
2840#ifdef DEBUG
2841 if (schema == NULL)
2842 xmlGenericError(xmlGenericErrorContext,
2843 "xmlSchemaParse() failed\n");
2844#endif
2845
2846 return (schema);
2847}
2848
2849/************************************************************************
2850 * *
2851 * Validating using Schemas *
2852 * *
2853 ************************************************************************/
2854
2855/************************************************************************
2856 * *
2857 * Reading/Writing Schemas *
2858 * *
2859 ************************************************************************/
2860
2861/**
2862 * xmlSchemaNewParserCtxt:
2863 * @URL: the location of the schema
2864 *
2865 * Create an XML Schemas parse context for that file/resource expected
2866 * to contain an XML Schemas file.
2867 *
2868 * Returns the parser context or NULL in case of error
2869 */
2870xmlSchemaParserCtxtPtr
2871xmlSchemaNewParserCtxt(const char *URL) {
2872 xmlSchemaParserCtxtPtr ret;
2873
2874 if (URL == NULL)
2875 return(NULL);
2876
2877 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
2878 if (ret == NULL) {
2879 xmlGenericError(xmlGenericErrorContext,
2880 "Failed to allocate new schama parser context for %s\n", URL);
2881 return (NULL);
2882 }
2883 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
2884 ret->URL = xmlStrdup((const xmlChar *)URL);
2885 return (ret);
2886}
2887
2888/**
2889 * xmlSchemaFreeParserCtxt:
2890 * @ctxt: the schema parser context
2891 *
2892 * Free the resources associated to the schema parser context
2893 */
2894void
2895xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) {
2896 if (ctxt == NULL)
2897 return;
2898 if (ctxt->URL != NULL)
2899 xmlFree(ctxt->URL);
2900 xmlFree(ctxt);
2901}
2902
2903/************************************************************************
2904 * *
2905 * Building the content models *
2906 * *
2907 ************************************************************************/
2908/**
2909 * xmlSchemaBuildAContentModel:
2910 * @type: the schema type definition
2911 * @ctxt: the schema parser context
2912 * @name: the element name whose content is being built
2913 *
2914 * Generate the automata sequence needed for that type
2915 */
2916static void
2917xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
2918 xmlSchemaParserCtxtPtr ctxt,
2919 const xmlChar *name) {
2920 if (type == NULL) {
2921 xmlGenericError(xmlGenericErrorContext,
2922 "Found unexpected type = NULL in %s content model\n",
2923 name);
2924 return;
2925 }
2926 switch (type->type) {
2927 case XML_SCHEMA_TYPE_ANY:
2928 /* TODO : handle the namespace too */
2929 /* TODO : make that a specific transition type */
2930 TODO
2931 ctxt->state = xmlAutomataNewTransition(ctxt->am, ctxt->state,
2932 NULL, BAD_CAST "*", NULL);
2933 break;
2934 case XML_SCHEMA_TYPE_ELEMENT: {
2935 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
2936 /* TODO : handle the namespace too */
2937 xmlAutomataStatePtr oldstate = ctxt->state;
2938 if (elem->maxOccurs >= UNBOUNDED) {
2939 if (elem->refDecl != NULL) {
2940 xmlSchemaBuildAContentModel(
2941 (xmlSchemaTypePtr) elem->refDecl,
2942 ctxt, elem->refDecl->name);
2943 } else {
2944 ctxt->state = xmlAutomataNewTransition(ctxt->am,
2945 ctxt->state, NULL, elem->name, type);
2946 }
2947 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
2948 if (elem->minOccurs == 0) {
2949 /* basically an elem* */
2950 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
2951 }
2952 } else if (elem->maxOccurs > 1) {
2953 if (elem->refDecl != NULL) {
2954 TODO
2955 xmlSchemaBuildAContentModel(
2956 (xmlSchemaTypePtr) elem->refDecl,
2957 ctxt, elem->refDecl->name);
2958 } else {
2959 ctxt->state = xmlAutomataNewCountTrans(ctxt->am,
2960 ctxt->state, NULL, elem->name,
2961 elem->minOccurs, elem->maxOccurs, type);
2962 }
2963 } else {
2964 if (elem->refDecl != NULL) {
2965 xmlSchemaBuildAContentModel(
2966 (xmlSchemaTypePtr) elem->refDecl,
2967 ctxt, elem->refDecl->name);
2968 } else {
2969 ctxt->state = xmlAutomataNewTransition(ctxt->am,
2970 ctxt->state, NULL, elem->name, type);
2971 }
2972 if (elem->minOccurs == 0) {
2973 /* basically an elem? */
2974 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
2975 }
2976 }
2977 break;
2978 }
2979 case XML_SCHEMA_TYPE_SEQUENCE: {
2980 xmlSchemaTypePtr subtypes;
2981
2982 /*
2983 * Simply iterate over the subtypes
2984 */
2985 subtypes = type->subtypes;
2986 while (subtypes != NULL) {
2987 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
2988 subtypes = subtypes->next;
2989 }
2990 break;
2991 }
2992 case XML_SCHEMA_TYPE_CHOICE: {
2993 xmlSchemaTypePtr subtypes;
2994 xmlAutomataStatePtr start, end;
2995
2996 start = ctxt->state;
2997 end = xmlAutomataNewState(ctxt->am);
2998
2999 /*
3000 * iterate over the subtypes and remerge the end with an
3001 * epsilon transition
3002 */
Daniel Veillardb509f152002-04-17 16:28:10 +00003003 if (type->maxOccurs == 1) {
3004 subtypes = type->subtypes;
3005 while (subtypes != NULL) {
3006 ctxt->state = start;
3007 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3008 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
3009 subtypes = subtypes->next;
3010 }
3011 } else {
3012 int counter;
3013 xmlAutomataStatePtr hop;
3014
3015 /*
3016 * use a counter to keep track of the number of transtions
3017 * which went through the choice.
3018 */
3019 if (type->minOccurs < 1) {
3020 counter = xmlAutomataNewCounter(ctxt->am, 0,
3021 type->maxOccurs - 1);
3022 } else {
3023 counter = xmlAutomataNewCounter(ctxt->am,
3024 type->minOccurs - 1, type->maxOccurs - 1);
3025 }
3026 hop = xmlAutomataNewState(ctxt->am);
3027
3028 subtypes = type->subtypes;
3029 while (subtypes != NULL) {
3030 ctxt->state = start;
3031 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3032 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
3033 subtypes = subtypes->next;
3034 }
3035 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
3036 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
3037 }
3038 if (type->minOccurs == 0) {
3039 xmlAutomataNewEpsilon(ctxt->am, start, end);
Daniel Veillard4255d502002-04-16 15:50:10 +00003040 }
3041 ctxt->state = end;
3042 break;
3043 }
3044 case XML_SCHEMA_TYPE_ALL: {
Daniel Veillard7646b182002-04-20 06:41:40 +00003045 xmlAutomataStatePtr start;
3046 xmlSchemaTypePtr subtypes;
3047 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard441bc322002-04-20 17:38:48 +00003048 int lax;
Daniel Veillard7646b182002-04-20 06:41:40 +00003049
3050 subtypes = type->subtypes;
3051 if (subtypes == NULL)
3052 break;
3053 start = ctxt->state;
3054 while (subtypes != NULL) {
3055 ctxt->state = start;
3056 elem = (xmlSchemaElementPtr) subtypes;
3057
3058 /* TODO : handle the namespace too */
3059 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state, ctxt->state,
3060 elem->name, elem->minOccurs, elem->maxOccurs,
3061 subtypes);
3062 subtypes = subtypes->next;
3063 }
Daniel Veillard441bc322002-04-20 17:38:48 +00003064 lax = type->minOccurs == 0;
3065 ctxt->state = xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
3066 lax);
Daniel Veillard4255d502002-04-16 15:50:10 +00003067 break;
3068 }
3069 case XML_SCHEMA_TYPE_RESTRICTION:
Daniel Veillardb4398962002-04-19 07:01:55 +00003070 if (type->subtypes != NULL)
Daniel Veillard6231e842002-04-18 11:54:04 +00003071 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3072 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003073 case XML_SCHEMA_TYPE_EXTENSION:
Daniel Veillard6231e842002-04-18 11:54:04 +00003074 if (type->baseType != NULL) {
3075 xmlSchemaTypePtr subtypes;
3076
3077 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
3078 subtypes = type->subtypes;
3079 while (subtypes != NULL) {
3080 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3081 subtypes = subtypes->next;
3082 }
3083 } else if (type->subtypes != NULL)
3084 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3085 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003086 case XML_SCHEMA_TYPE_GROUP:
3087 case XML_SCHEMA_TYPE_COMPLEX:
3088 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
3089 if (type->subtypes != NULL)
3090 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3091 break;
3092 default:
3093 xmlGenericError(xmlGenericErrorContext,
3094 "Found unexpected type %d in %s content model\n",
3095 type->type, name);
3096 return;
3097 }
3098}
3099/**
3100 * xmlSchemaBuildContentModel:
3101 * @typeDecl: the schema type definition
3102 * @ctxt: the schema parser context
3103 *
3104 * Fixes the content model of the element.
3105 */
3106static void
3107xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
3108 xmlSchemaParserCtxtPtr ctxt,
3109 const xmlChar *name) {
3110 xmlAutomataStatePtr start;
3111
Daniel Veillard4255d502002-04-16 15:50:10 +00003112 if (elem->contModel != NULL)
3113 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003114 if (elem->subtypes == NULL) {
3115 elem->contentType = XML_SCHEMA_CONTENT_ANY;
Daniel Veillard4255d502002-04-16 15:50:10 +00003116 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003117 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003118 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
3119 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003120 if (elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC)
3121 return;
3122
3123#ifdef DEBUG_CONTENT
3124 xmlGenericError(xmlGenericErrorContext,
3125 "Building content model for %s\n", name);
3126#endif
3127
Daniel Veillard4255d502002-04-16 15:50:10 +00003128 ctxt->am = xmlNewAutomata();
3129 if (ctxt->am == NULL) {
3130 xmlGenericError(xmlGenericErrorContext,
3131 "Cannot create automata for elem %s\n", name);
3132 return;
3133 }
3134 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3135 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3136 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillarde19fc232002-04-22 16:01:24 +00003137 if (!xmlAutomataIsDeterminist(ctxt->am)) {
3138 xmlGenericError(xmlGenericErrorContext,
3139 "Content model of %s is not determinist:\n", name);
3140 elem->contModel = xmlAutomataCompile(ctxt->am);
3141 ctxt->err = XML_SCHEMAS_ERR_NOTDETERMINIST;
3142 } else {
3143 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillard4255d502002-04-16 15:50:10 +00003144#ifdef DEBUG_CONTENT
Daniel Veillarde19fc232002-04-22 16:01:24 +00003145 xmlGenericError(xmlGenericErrorContext,
3146 "Content model of %s:\n", name);
3147 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003148#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00003149 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003150 ctxt->state = NULL;
3151 xmlFreeAutomata(ctxt->am);
3152 ctxt->am = NULL;
3153}
3154
3155/**
3156 * xmlSchemaRefFixupCallback:
3157 * @elem: the schema element context
3158 * @ctxt: the schema parser context
3159 *
3160 * Free the resources associated to the schema parser context
3161 */
3162static void
3163xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
3164 xmlSchemaParserCtxtPtr ctxt,
3165 const xmlChar *name,
3166 ATTRIBUTE_UNUSED const xmlChar *context,
3167 ATTRIBUTE_UNUSED const xmlChar *namespace)
3168{
3169 if ((ctxt == NULL) || (elem == NULL))
3170 return;
3171 if (elem->ref != NULL) {
3172 xmlSchemaElementPtr elemDecl;
3173
3174 if (elem->subtypes != NULL) {
3175 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3176 if ((ctxt != NULL) && (ctxt->error != NULL))
3177 ctxt->error(ctxt->userData,
3178 "Schemas: element %s have both ref and subtype\n",
3179 name);
3180 return;
3181 }
3182 elemDecl = xmlHashLookup2(ctxt->schema->elemDecl,
3183 elem->ref, elem->refNs);
3184
3185 if (elemDecl == NULL) {
3186 if ((ctxt != NULL) && (ctxt->error != NULL))
3187 ctxt->error(ctxt->userData,
3188 "Schemas: element %s ref to %s not found\n",
3189 name, elem->ref);
3190 return;
3191 }
3192 elem->refDecl = elemDecl;
3193 } else if (elem->namedType != NULL) {
3194 xmlSchemaTypePtr typeDecl;
3195
3196 if (elem->subtypes != NULL) {
3197 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3198 if ((ctxt != NULL) && (ctxt->error != NULL))
3199 ctxt->error(ctxt->userData,
3200 "Schemas: element %s have both type and subtype\n",
3201 name);
3202 return;
3203 }
3204 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3205 elem->namedTypeNs);
3206
3207 if (typeDecl == NULL) {
3208 if ((ctxt != NULL) && (ctxt->error != NULL))
3209 ctxt->error(ctxt->userData,
3210 "Schemas: element %s type %s not found\n",
3211 name, elem->namedType);
3212 return;
3213 }
3214 elem->subtypes = typeDecl;
3215 }
3216}
3217
3218/**
3219 * xmlSchemaTypeFixup:
3220 * @typeDecl: the schema type definition
3221 * @ctxt: the schema parser context
3222 *
3223 * Fixes the content model of the type.
3224 */
3225static void
3226xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
3227 xmlSchemaParserCtxtPtr ctxt,
3228 const xmlChar *name)
3229{
3230 if (name == NULL)
3231 name = typeDecl->name;
3232 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
3233 switch (typeDecl->type) {
3234 case XML_SCHEMA_TYPE_SIMPLE_CONTENT: {
3235 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3236 typeDecl->contentType = typeDecl->subtypes->contentType;
3237 break;
3238 }
3239 case XML_SCHEMA_TYPE_RESTRICTION: {
3240 if (typeDecl->subtypes != NULL)
3241 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3242
3243 if (typeDecl->base != NULL) {
3244 xmlSchemaTypePtr baseType;
3245
3246 baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3247 typeDecl->baseNs);
3248 if (baseType == NULL) {
3249 if ((ctxt != NULL) && (ctxt->error != NULL))
3250 ctxt->error(ctxt->userData,
3251 "Schemas: type %s base type %s not found\n",
3252 name, typeDecl->base);
3253 }
3254 typeDecl->baseType = baseType;
3255 }
3256 if (typeDecl->subtypes == NULL)
3257 /* 1.1.1 */
3258 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3259 else if ((typeDecl->subtypes->subtypes == NULL) &&
3260 ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3261 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3262 /* 1.1.2 */
3263 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3264 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3265 (typeDecl->subtypes->subtypes == NULL))
3266 /* 1.1.3 */
3267 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3268 else {
3269 /* 1.2 and 2.X are applied at the other layer */
3270 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3271 }
3272 break;
3273 }
3274 case XML_SCHEMA_TYPE_EXTENSION: {
3275 xmlSchemaContentType explicitContentType;
3276 xmlSchemaTypePtr base;
3277
3278 if (typeDecl->base != NULL) {
3279 xmlSchemaTypePtr baseType;
3280
3281 baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3282 typeDecl->baseNs);
3283 if (baseType == NULL) {
3284 if ((ctxt != NULL) && (ctxt->error != NULL))
3285 ctxt->error(ctxt->userData,
3286 "Schemas: type %s base type %s not found\n",
3287 name, typeDecl->base);
3288 }
3289 typeDecl->baseType = baseType;
3290 }
3291 if (typeDecl->subtypes != NULL)
3292 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3293
Daniel Veillard8651f532002-04-17 09:06:27 +00003294 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillard4255d502002-04-16 15:50:10 +00003295 if (typeDecl->subtypes == NULL)
3296 /* 1.1.1 */
3297 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3298 else if ((typeDecl->subtypes->subtypes == NULL) &&
3299 ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3300 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3301 /* 1.1.2 */
3302 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3303 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3304 (typeDecl->subtypes->subtypes == NULL))
3305 /* 1.1.3 */
3306 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3307
3308 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3309 typeDecl->baseNs);
3310 if (base == NULL) {
3311 xmlSchemaErrorContext(ctxt, NULL, typeDecl->node, NULL);
3312 if ((ctxt != NULL) && (ctxt->error != NULL))
3313 ctxt->error(ctxt->userData,
3314 "Schemas: base type %s of type %s not found\n",
3315 typeDecl->base, name);
3316 return;
3317 }
3318 xmlSchemaTypeFixup(base, ctxt, NULL);
3319 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
3320 /* 2.1 */
3321 typeDecl->contentType = base->contentType;
3322 } else if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
3323 /* 2.2 imbitable ! */
3324 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3325 } else {
3326 /* 2.3 imbitable pareil ! */
3327 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3328 }
3329 break;
3330 }
3331 case XML_SCHEMA_TYPE_COMPLEX: {
3332 if (typeDecl->subtypes == NULL) {
3333 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3334 } else {
3335 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3336 typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3337 else {
3338 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3339 typeDecl->contentType = typeDecl->subtypes->contentType;
3340 }
3341 }
3342 break;
3343 }
3344 case XML_SCHEMA_TYPE_COMPLEX_CONTENT: {
3345 if (typeDecl->subtypes == NULL) {
3346 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3347 } else {
3348 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3349 typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3350 else {
3351 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3352 typeDecl->contentType = typeDecl->subtypes->contentType;
3353 }
3354 }
3355 break;
3356 }
3357 case XML_SCHEMA_TYPE_SEQUENCE:
3358 case XML_SCHEMA_TYPE_GROUP:
3359 case XML_SCHEMA_TYPE_ALL:
3360 case XML_SCHEMA_TYPE_CHOICE:
3361 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3362 break;
3363 case XML_SCHEMA_TYPE_BASIC:
3364 case XML_SCHEMA_TYPE_ANY:
3365 case XML_SCHEMA_TYPE_FACET:
3366 case XML_SCHEMA_TYPE_SIMPLE:
3367 case XML_SCHEMA_TYPE_UR:
3368 case XML_SCHEMA_TYPE_ELEMENT:
3369 case XML_SCHEMA_TYPE_ATTRIBUTE:
3370 case XML_SCHEMA_TYPE_NOTATION:
3371 case XML_SCHEMA_TYPE_LIST:
3372 case XML_SCHEMA_TYPE_UNION:
3373 case XML_SCHEMA_FACET_MININCLUSIVE:
3374 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3375 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3376 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
3377 case XML_SCHEMA_FACET_TOTALDIGITS:
3378 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3379 case XML_SCHEMA_FACET_PATTERN:
3380 case XML_SCHEMA_FACET_ENUMERATION:
3381 case XML_SCHEMA_FACET_WHITESPACE:
3382 case XML_SCHEMA_FACET_LENGTH:
3383 case XML_SCHEMA_FACET_MAXLENGTH:
3384 case XML_SCHEMA_FACET_MINLENGTH:
3385 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
3386 break;
3387 }
3388 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003389#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003390 if (typeDecl->node != NULL) {
3391 xmlGenericError(xmlGenericErrorContext,
3392 "Type of %s : %s:%d :", name, typeDecl->node->doc->URL,
3393 xmlGetLineNo(typeDecl->node));
3394 } else {
3395 xmlGenericError(xmlGenericErrorContext,
3396 "Type of %s :", name);
3397 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003398 switch (typeDecl->contentType) {
3399 case XML_SCHEMA_CONTENT_SIMPLE:
3400 xmlGenericError(xmlGenericErrorContext,
3401 "simple\n"); break;
3402 case XML_SCHEMA_CONTENT_ELEMENTS:
3403 xmlGenericError(xmlGenericErrorContext,
3404 "elements\n"); break;
3405 case XML_SCHEMA_CONTENT_UNKNOWN:
3406 xmlGenericError(xmlGenericErrorContext,
3407 "unknown !!!\n"); break;
3408 case XML_SCHEMA_CONTENT_EMPTY:
3409 xmlGenericError(xmlGenericErrorContext,
3410 "empty\n"); break;
3411 case XML_SCHEMA_CONTENT_MIXED:
3412 xmlGenericError(xmlGenericErrorContext,
3413 "mixed\n"); break;
3414 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
3415 xmlGenericError(xmlGenericErrorContext,
3416 "mixed or elems\n"); break;
3417 case XML_SCHEMA_CONTENT_BASIC:
3418 xmlGenericError(xmlGenericErrorContext,
3419 "basic\n"); break;
3420 default:
3421 xmlGenericError(xmlGenericErrorContext,
3422 "not registered !!!\n"); break;
3423 }
3424#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003425}
3426
3427/**
3428 * xmlSchemaCheckDefaults:
3429 * @typeDecl: the schema type definition
3430 * @ctxt: the schema parser context
3431 *
3432 * Checks the default values types, especially for facets
3433 */
3434static void
3435xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
3436 xmlSchemaParserCtxtPtr ctxt,
3437 const xmlChar *name)
3438{
3439 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
3440 if (name == NULL)
3441 name = typeDecl->name;
3442 if (nonNegativeIntegerType == NULL) {
3443 nonNegativeIntegerType = xmlSchemaGetPredefinedType(
3444 BAD_CAST "nonNegativeInteger", xmlSchemaNs);
3445 }
3446 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
3447 if (typeDecl->facets != NULL) {
3448 xmlSchemaFacetPtr facet = typeDecl->facets;
3449 while (facet != NULL) {
3450 switch (facet->type) {
3451 case XML_SCHEMA_FACET_MININCLUSIVE:
3452 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3453 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3454 case XML_SCHEMA_FACET_MAXEXCLUSIVE: {
3455 /*
3456 * Okay we need to validate the value
3457 * at that point.
3458 */
3459 xmlSchemaValidCtxtPtr vctxt;
3460
3461 vctxt = xmlSchemaNewValidCtxt(NULL);
3462 if (vctxt == NULL)
3463 break;
3464 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3465 facet->value);
3466 facet->val = vctxt->value;
3467 vctxt->value = NULL;
3468 if (facet->val == NULL) {
3469 /* error code */
3470 xmlSchemaErrorContext(ctxt, NULL,
3471 facet->node, NULL);
3472 ctxt->error(ctxt->userData,
3473 "Schemas: type %s facet value %s invalid\n",
3474 name, facet->value);
3475 }
3476 xmlSchemaFreeValidCtxt(vctxt);
3477 break;
3478 }
3479 case XML_SCHEMA_FACET_ENUMERATION: {
3480 /*
3481 * Okay we need to validate the value
3482 * at that point.
3483 */
3484 xmlSchemaValidCtxtPtr vctxt;
3485 int ret;
3486
3487 vctxt = xmlSchemaNewValidCtxt(NULL);
3488 if (vctxt == NULL)
3489 break;
3490 ret = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3491 facet->value);
3492 if (ret != 0) {
3493 xmlSchemaErrorContext(ctxt, NULL,
3494 facet->node, NULL);
3495 ctxt->error(ctxt->userData,
3496 "Schemas: type %s enumeration value %s invalid\n",
3497 name, facet->value);
3498 }
3499 xmlSchemaFreeValidCtxt(vctxt);
3500 break;
3501 }
3502 case XML_SCHEMA_FACET_PATTERN:
3503 facet->regexp = xmlRegexpCompile(facet->value);
3504 if (facet->regexp == NULL) {
3505 /* error code */
3506 ctxt->error(ctxt->userData,
3507 "Schemas: type %s facet regexp %s invalid\n",
3508 name, facet->value);
3509 }
3510 break;
3511 case XML_SCHEMA_FACET_TOTALDIGITS:
3512 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3513 case XML_SCHEMA_FACET_LENGTH:
3514 case XML_SCHEMA_FACET_MAXLENGTH:
3515 case XML_SCHEMA_FACET_MINLENGTH: {
3516 int ret;
3517
3518 ret = xmlSchemaValidatePredefinedType(
3519 nonNegativeIntegerType, facet->value,
3520 &facet->val);
3521 if (ret != 0) {
3522 /* error code */
3523 xmlSchemaErrorContext(ctxt, NULL,
3524 facet->node, NULL);
3525 ctxt->error(ctxt->userData,
3526 "Schemas: type %s facet value %s invalid\n",
3527 name, facet->value);
3528 }
3529 break;
3530 }
3531 case XML_SCHEMA_FACET_WHITESPACE: {
3532 if (xmlStrEqual(facet->value, BAD_CAST"preserve")) {
3533 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
3534 } else if (xmlStrEqual(facet->value,
3535 BAD_CAST"replace")) {
3536 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
3537 } else if (xmlStrEqual(facet->value,
3538 BAD_CAST"collapse")) {
3539 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
3540 } else {
3541 xmlSchemaErrorContext(ctxt, NULL,
3542 facet->node, NULL);
3543 ctxt->error(ctxt->userData,
3544 "Schemas: type %s whiteSpace value %s invalid\n",
3545 name, facet->value);
3546 }
3547 }
3548 default:
3549 break;
3550 }
3551 facet = facet->next;
3552 }
3553 }
3554 }
3555}
3556
3557/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00003558 * xmlSchemaAttrGrpFixup:
3559 * @attrgrpDecl: the schema attribute definition
3560 * @ctxt: the schema parser context
3561 * @name: the attribute name
3562 *
3563 * Fixes finish doing the computations on the attributes definitions
3564 */
3565static void
3566xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
3567 xmlSchemaParserCtxtPtr ctxt,
3568 const xmlChar *name)
3569{
3570 if (name == NULL)
3571 name = attrgrpDecl->name;
3572 if (attrgrpDecl->attributes != NULL)
3573 return;
3574 if (attrgrpDecl->ref != NULL) {
3575 xmlSchemaAttributeGroupPtr ref;
3576
3577 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
3578 attrgrpDecl->refNs);
3579 if (ref == NULL) {
3580 if ((ctxt != NULL) && (ctxt->error != NULL))
3581 ctxt->error(ctxt->userData,
3582 "Schemas: attribute group %s reference %s not found\n",
3583 name, attrgrpDecl->ref);
3584 return;
3585 }
3586 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
3587 attrgrpDecl->attributes = ref->attributes;
3588 } else {
3589 if ((ctxt != NULL) && (ctxt->error != NULL))
3590 ctxt->error(ctxt->userData,
3591 "Schemas: attribute %s has no attributes nor reference\n",
3592 name);
3593 }
3594}
3595
3596/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003597 * xmlSchemaAttrFixup:
3598 * @attrDecl: the schema attribute definition
3599 * @ctxt: the schema parser context
3600 * @name: the attribute name
3601 *
3602 * Fixes finish doing the computations on the attributes definitions
3603 */
3604static void
3605xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
3606 xmlSchemaParserCtxtPtr ctxt,
3607 const xmlChar *name)
3608{
3609 if (name == NULL)
3610 name = attrDecl->name;
3611 if (attrDecl->subtypes != NULL)
3612 return;
3613 if (attrDecl->typeName != NULL) {
3614 xmlSchemaTypePtr type;
3615
3616 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
3617 attrDecl->typeNs);
3618 if (type == NULL) {
3619 if ((ctxt != NULL) && (ctxt->error != NULL))
3620 ctxt->error(ctxt->userData,
3621 "Schemas: attribute %s type %s not found\n",
3622 name, attrDecl->typeName);
3623 }
3624 attrDecl->subtypes = type;
3625 } else if (attrDecl->ref != NULL) {
3626 xmlSchemaAttributePtr ref;
3627
3628 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
3629 attrDecl->refNs);
3630 if (ref == NULL) {
3631 if ((ctxt != NULL) && (ctxt->error != NULL))
3632 ctxt->error(ctxt->userData,
3633 "Schemas: attribute %s reference %s not found\n",
3634 name, attrDecl->ref);
3635 return;
3636 }
3637 xmlSchemaAttrFixup(ref, ctxt, NULL);
3638 attrDecl->subtypes = ref->subtypes;
3639 } else {
3640 if ((ctxt != NULL) && (ctxt->error != NULL))
3641 ctxt->error(ctxt->userData,
3642 "Schemas: attribute %s has no type nor reference\n",
3643 name);
3644 }
3645}
3646
3647/**
3648 * xmlSchemaParse:
3649 * @ctxt: a schema validation context
3650 * @URL: the location of the schema
3651 *
3652 * Load, XML parse a schema definition resource and build an internal
3653 * XML Shema struture which can be used to validate instances.
3654 * *WARNING* this interface is highly subject to change
3655 *
3656 * Returns the internal XML Schema structure built from the resource or
3657 * NULL in case of error
3658 */
3659xmlSchemaPtr
3660xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
3661{
3662 xmlSchemaPtr ret = NULL;
3663 xmlDocPtr doc;
3664 xmlNodePtr root, cur, delete;
3665
3666 xmlSchemaInitTypes();
3667
3668 if ((ctxt == NULL) || (ctxt->URL == NULL))
3669 return (NULL);
3670
3671 ctxt->counter = 0;
3672 ctxt->container = NULL;
3673
3674 /*
3675 * First step is to parse the input document into an DOM/Infoset
3676 */
3677 doc = xmlParseFile((const char *) ctxt->URL);
3678 if (doc == NULL) {
3679 if (ctxt->error != NULL)
3680 ctxt->error(ctxt->userData,
3681 "xmlSchemaParse: could not load %s\n", ctxt->URL);
3682 return (NULL);
3683 }
3684
3685 /*
3686 * Then extract the root and Schema parse it
3687 */
3688 root = xmlDocGetRootElement(doc);
3689 if (root == NULL) {
3690 if (ctxt->error != NULL)
3691 ctxt->error(ctxt->userData, "xmlSchemaParse: %s is empty\n",
3692 ctxt->URL);
3693 return (NULL);
3694 }
3695
3696 /*
3697 * Remove all the blank text nodes
3698 */
3699 delete = NULL;
3700 cur = root;
3701 while (cur != NULL) {
3702 if (delete != NULL) {
3703 xmlUnlinkNode(delete);
3704 xmlFreeNode(delete);
3705 delete = NULL;
3706 }
3707 if (cur->type == XML_TEXT_NODE) {
3708 if (IS_BLANK_NODE(cur)) {
3709 if (xmlNodeGetSpacePreserve(cur) != 1) {
3710 delete = cur;
3711 }
3712 }
3713 } else if ((cur->type != XML_ELEMENT_NODE) &&
3714 (cur->type != XML_CDATA_SECTION_NODE)) {
3715 delete = cur;
3716 goto skip_children;
3717 }
3718
3719 /*
3720 * Skip to next node
3721 */
3722 if (cur->children != NULL) {
3723 if ((cur->children->type != XML_ENTITY_DECL) &&
3724 (cur->children->type != XML_ENTITY_REF_NODE) &&
3725 (cur->children->type != XML_ENTITY_NODE)) {
3726 cur = cur->children;
3727 continue;
3728 }
3729 }
3730skip_children:
3731 if (cur->next != NULL) {
3732 cur = cur->next;
3733 continue;
3734 }
3735
3736 do {
3737 cur = cur->parent;
3738 if (cur == NULL)
3739 break;
3740 if (cur == root) {
3741 cur = NULL;
3742 break;
3743 }
3744 if (cur->next != NULL) {
3745 cur = cur->next;
3746 break;
3747 }
3748 } while (cur != NULL);
3749 }
3750 if (delete != NULL) {
3751 xmlUnlinkNode(delete);
3752 xmlFreeNode(delete);
3753 delete = NULL;
3754 }
3755
3756 /*
3757 * Then do the parsing for good
3758 */
3759 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillardb4398962002-04-19 07:01:55 +00003760 if (ret == NULL)
3761 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003762 ret->doc = doc;
3763
3764 /*
3765 * Then fix all the references.
3766 */
3767 ctxt->schema = ret;
3768 xmlHashScanFull(ret->elemDecl,
3769 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
3770
3771 /*
3772 * Then fixup all types properties
3773 */
3774 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
3775
3776 /*
3777 * Then build the content model for all elements
3778 */
3779 xmlHashScan(ret->elemDecl,
3780 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
3781
3782 /*
3783 * Then check the defaults part of the type like facets values
3784 */
3785 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt);
3786
3787 /*
3788 * Then fixup all attributes declarations
3789 */
3790 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
3791
Daniel Veillard13e04c62002-04-23 17:51:29 +00003792 /*
3793 * Then fixup all attributes group declarations
3794 */
3795 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup, ctxt);
3796
Daniel Veillard4255d502002-04-16 15:50:10 +00003797 return (ret);
3798}
3799
3800/**
3801 * xmlSchemaParse:
3802 * @ctxt: a schema validation context
3803 * @URL: the location of the schema
3804 *
3805 * Load, XML parse a schema definition resource and build an internal
3806 * XML Shema struture which can be used to validate instances.
3807 * *WARNING* this interface is highly subject to change
3808 *
3809 * Returns the internal XML Schema structure built from the resource or
3810 * NULL in case of error
3811 */
3812void
3813xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
3814 xmlSchemaValidityErrorFunc err,
3815 xmlSchemaValidityWarningFunc warn, void *ctx) {
3816 if (ctxt == NULL)
3817 return;
3818 ctxt->error = err;
3819 ctxt->warning = warn;
3820 ctxt->userData = ctx;
3821}
3822
3823/************************************************************************
3824 * *
3825 * Simple type validation *
3826 * *
3827 ************************************************************************/
3828
3829/**
3830 * xmlSchemaValidateSimpleValue:
3831 * @ctxt: a schema validation context
3832 * @type: the type declaration
3833 * @value: the value to validate
3834 *
3835 * Validate a value against a simple type
3836 *
3837 * Returns 0 if the value is valid, a positive error code
3838 * number otherwise and -1 in case of internal or API error.
3839 */
3840static int
3841xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
3842 xmlSchemaTypePtr type,
3843 xmlChar *value) {
3844 int ret = 0;
3845 /*
3846 * First normalize the value accordingly to Schema Datatype
3847 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
3848 */
3849 /*
3850 * Then check the normalized value against the lexical space of the
3851 * type.
3852 */
3853 if (type->type == XML_SCHEMA_TYPE_BASIC) {
3854 if (ctxt->value != NULL) {
3855 xmlSchemaFreeValue(ctxt->value);
3856 ctxt->value = NULL;
3857 }
3858 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
3859 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
3860 xmlSchemaTypePtr base;
3861 xmlSchemaFacetPtr facet;
3862 int tmp;
3863
3864 base = type->baseType;
3865 if (base != NULL) {
3866 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
3867 } else if (type->subtypes != NULL) {
3868
3869 }
3870 /*
3871 * Do not validate facets when working on building the Schemas
3872 */
3873 if (ctxt->schema != NULL) {
3874 if (ret == 0) {
3875 facet = type->facets;
Daniel Veillard88c58912002-04-23 07:12:20 +00003876 if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) &&
3877 (facet != NULL) &&
3878 (facet->type == XML_SCHEMA_FACET_ENUMERATION)) {
3879 while (facet != NULL) {
3880 ret = 1;
3881
3882 tmp = xmlSchemaValidateFacet(base, facet, value,
3883 ctxt->value);
3884 if (tmp == 0) {
3885 ret = 0;
3886 break;
3887 }
3888 facet = facet->next;
3889 }
3890 } else {
3891 while (facet != NULL) {
3892 tmp = xmlSchemaValidateFacet(base, facet, value,
3893 ctxt->value);
3894 if (tmp != 0)
3895 ret = tmp;
3896 facet = facet->next;
3897 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003898 }
3899 }
3900 }
3901 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
3902 xmlSchemaTypePtr base;
3903
3904 base = type->subtypes;
3905 if (base != NULL) {
3906 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
3907 } else {
3908 TODO
3909 }
3910 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
3911 xmlSchemaTypePtr base;
3912 xmlChar *cur, *end, tmp;
3913 int ret2;
3914
3915 base = type->subtypes;
3916 if (base == NULL) {
3917 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
3918 if (ctxt->error != NULL) {
3919 xmlSchemaErrorContext(NULL, ctxt->schema, type->node, NULL);
3920 ctxt->error(ctxt->userData,
3921 "Internal: List type %s has no base type\n",
3922 type->name);
3923 }
3924 return(-1);
3925 }
3926 cur = value;
3927 do {
3928 while (IS_BLANK(*cur)) cur++;
3929 end = cur;
3930 while ((*end != 0) && (!(IS_BLANK(*end)))) end++;
3931 if (end == cur)
3932 break;
3933 tmp = *end;
3934 *end = 0;
3935 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, cur);
3936 if (ret2 != 0)
3937 ret = 1;
3938 *end = tmp;
3939 cur = end;
3940 } while (*cur != 0);
3941 } else {
3942 TODO
3943 }
3944 return(ret);
3945}
3946
3947/************************************************************************
3948 * *
3949 * DOM Validation code *
3950 * *
3951 ************************************************************************/
3952
3953static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
3954 xmlNodePtr node);
3955static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
3956 xmlNodePtr elem, xmlSchemaAttributePtr attributes);
3957static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
3958 xmlNodePtr elem, xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type);
3959
3960/**
3961 * xmlSchemaRegisterAttributes:
3962 * @ctxt: a schema validation context
3963 * @attrs: a list of attributes
3964 *
3965 * Register the list of attributes as the set to be validated on that element
3966 *
3967 * Returns -1 in case of error, 0 otherwise
3968 */
3969static int
3970xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt,
3971 xmlAttrPtr attrs) {
3972 while (attrs != NULL) {
Daniel Veillard441bc322002-04-20 17:38:48 +00003973 if ((attrs->ns != NULL) &&
3974 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
3975 attrs = attrs->next;
3976 continue;
3977 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003978 if (ctxt->attrNr >= ctxt->attrMax) {
3979 xmlSchemaAttrStatePtr tmp;
3980
3981 ctxt->attrMax *= 2;
3982 tmp = (xmlSchemaAttrStatePtr)
3983 xmlRealloc(ctxt->attr, ctxt->attrMax *
3984 sizeof(xmlSchemaAttrState));
3985 if (tmp == NULL) {
3986 ctxt->attrMax /= 2;
3987 return(-1);
3988 }
3989 ctxt->attr = tmp;
3990 }
3991 ctxt->attr[ctxt->attrNr].attr = attrs;
3992 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
3993 ctxt->attrNr++;
3994 attrs = attrs->next;
3995 }
3996 return(0);
3997}
3998
3999/**
4000 * xmlSchemaCheckAttributes:
4001 * @ctxt: a schema validation context
4002 * @node: the node carrying it.
4003 *
4004 * Check that the registered set of attributes on the current node
4005 * has been properly validated.
4006 *
4007 * Returns 0 if validity constraints are met, 1 otherwise.
4008 */
4009static int
4010xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4011 int ret = 0;
4012 int i;
4013
4014 for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
4015 if (ctxt->attr[i].attr == NULL)
4016 break;
4017 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
4018 ret = 1;
4019 ctxt->err = XML_SCHEMAS_ERR_ATTRUNKNOWN;
4020 if (ctxt->error != NULL)
4021 ctxt->error(ctxt->userData,
4022 "Attribute %s on %s is unknown\n",
4023 ctxt->attr[i].attr->name,
4024 node->name);
4025 }
4026 }
4027 return(ret);
4028}
4029
4030/**
4031 * xmlSchemaValidateSimpleContent:
4032 * @ctxt: a schema validation context
4033 * @elem: an element
4034 * @type: the type declaration
4035 *
4036 * Validate the content of an element expected to be a simple type
4037 *
4038 * Returns 0 if the element is schemas valid, a positive error code
4039 * number otherwise and -1 in case of internal or API error.
4040 */
4041static int
4042xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
4043 ATTRIBUTE_UNUSED xmlNodePtr node) {
4044 xmlNodePtr child;
4045 xmlSchemaTypePtr type, base;
4046 xmlChar *value;
4047 int ret = 0, tmp;
4048
4049 child = ctxt->node;
4050 type = ctxt->type;
4051
4052 /*
4053 * Validation Rule: Element Locally Valid (Type): 3.1.3
4054 */
4055 value = xmlNodeGetContent(child);
4056 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
4057 switch (type->type) {
4058 case XML_SCHEMA_TYPE_RESTRICTION: {
4059 xmlSchemaFacetPtr facet;
4060
4061 base = type->baseType;
4062 if (base != NULL) {
4063 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4064 } else {
4065 TODO
4066 }
4067 if (ret == 0) {
4068 facet = type->facets;
4069 while (facet != NULL) {
4070 tmp = xmlSchemaValidateFacet(base, facet, value,
4071 ctxt->value);
4072 if (tmp != 0)
4073 ret = tmp;
4074 facet = facet->next;
4075 }
4076 }
4077 break;
4078 }
4079 default:
4080 TODO
4081 }
4082 if (value != NULL)
4083 xmlFree(value);
4084
4085 return(ret);
4086}
4087
4088/**
4089 * xmlSchemaValidateCheckNodeList
4090 * @nodelist: the list of nodes
4091 *
4092 * Check the node list is only made of text nodes and entities pointing
4093 * to text nodes
4094 *
4095 * Returns 1 if true, 0 if false and -1 in case of error
4096 */
4097static int
4098xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist) {
4099 while (nodelist != NULL) {
4100 if (nodelist->type == XML_ENTITY_REF_NODE) {
4101 TODO /* implement recursion in the entity content */
4102 }
4103 if ((nodelist->type != XML_TEXT_NODE) &&
4104 (nodelist->type != XML_COMMENT_NODE) &&
4105 (nodelist->type != XML_PI_NODE) &&
4106 (nodelist->type != XML_PI_NODE)) {
4107 return(0);
4108 }
4109 nodelist = nodelist->next;
4110 }
4111 return(1);
4112}
4113
4114/**
4115 * xmlSchemaSkipIgnored:
4116 * @ctxt: a schema validation context
4117 * @type: the current type context
4118 * @node: the top node.
4119 *
4120 * Skip ignorable nodes in that context
4121 *
4122 * Returns the new sibling
4123 * number otherwise and -1 in case of internal or API error.
4124 */
4125static xmlNodePtr
4126xmlSchemaSkipIgnored(ATTRIBUTE_UNUSED xmlSchemaValidCtxtPtr ctxt,
4127 xmlSchemaTypePtr type,
4128 xmlNodePtr node) {
4129 int mixed = 0;
4130 /*
4131 * TODO complete and handle entities
4132 */
4133 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
4134 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
4135 while ((node != NULL) &&
4136 ((node->type == XML_COMMENT_NODE) ||
4137 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
4138 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
4139 (node->type == XML_TEXT_NODE) &&
4140 (IS_BLANK_NODE(node)))))) {
4141 node = node->next;
4142 }
4143 return(node);
4144}
4145
4146/**
4147 * xmlSchemaValidateCallback:
4148 * @ctxt: a schema validation context
4149 * @name: the name of the element detected (might be NULL)
4150 * @type: the type
4151 *
4152 * A transition has been made in the automata associated to an element
4153 * content model
4154 */
4155static void
4156xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
4157 ATTRIBUTE_UNUSED const xmlChar *name,
4158 xmlSchemaTypePtr type,
4159 xmlNodePtr node) {
4160 xmlSchemaTypePtr oldtype = ctxt->type;
4161 xmlNodePtr oldnode = ctxt->node;
4162#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00004163 xmlGenericError(xmlGenericErrorContext,
4164 "xmlSchemaValidateCallback: %s, %s, %s\n",
4165 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004166#endif
4167 ctxt->type = type;
4168 ctxt->node = node;
4169 xmlSchemaValidateContent(ctxt, node);
4170 ctxt->type = oldtype;
4171 ctxt->node = oldnode;
4172}
4173
4174
4175#if 0
4176/**
4177 * xmlSchemaValidateSimpleRestrictionType:
4178 * @ctxt: a schema validation context
4179 * @node: the top node.
4180 *
4181 * Validate the content of a restriction type.
4182 *
4183 * Returns 0 if the element is schemas valid, a positive error code
4184 * number otherwise and -1 in case of internal or API error.
4185 */
4186static int
4187xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
4188 xmlNodePtr node)
4189{
4190 xmlNodePtr child;
4191 xmlSchemaTypePtr type;
4192 int ret;
4193
4194 child = ctxt->node;
4195 type = ctxt->type;
4196
4197 if ((ctxt == NULL) || (type == NULL)) {
4198 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4199 if (ctxt->error != NULL)
4200 ctxt->error(ctxt->userData,
4201 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
4202 node->name);
4203 return (-1);
4204 }
4205 /*
4206 * Only text and text based entities references shall be found there
4207 */
4208 ret = xmlSchemaValidateCheckNodeList(child);
4209 if (ret < 0) {
4210 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4211 if (ctxt->error != NULL)
4212 ctxt->error(ctxt->userData,
4213 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4214 node->name);
4215 return (-1);
4216 } else if (ret == 0) {
4217 ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4218 if (ctxt->error != NULL)
4219 ctxt->error(ctxt->userData,
4220 "Element %s content is not a simple type\n",
4221 node->name);
4222 return (-1);
4223 }
4224 ctxt->type = type->subtypes;
4225 xmlSchemaValidateContent(ctxt, node);
4226 ctxt->type = type;
4227 return (ret);
4228}
4229#endif
4230
4231/**
4232 * xmlSchemaValidateSimpleType:
4233 * @ctxt: a schema validation context
4234 * @node: the top node.
4235 *
4236 * Validate the content of an simple type.
4237 *
4238 * Returns 0 if the element is schemas valid, a positive error code
4239 * number otherwise and -1 in case of internal or API error.
4240 */
4241static int
4242xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4243 xmlNodePtr child;
4244 xmlSchemaTypePtr type;
4245 xmlAttrPtr attr;
4246 int ret;
4247
4248 child = ctxt->node;
4249 type = ctxt->type;
4250
4251 if ((ctxt == NULL) || (type == NULL)) {
4252 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4253 if (ctxt->error != NULL)
4254 ctxt->error(ctxt->userData,
4255 "Internal error: xmlSchemaValidateSimpleType %s\n",
4256 node->name);
4257 return(-1);
4258 }
4259 /*
4260 * Only text and text based entities references shall be found there
4261 */
4262 ret = xmlSchemaValidateCheckNodeList(child);
4263 if (ret < 0) {
4264 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4265 if (ctxt->error != NULL)
4266 ctxt->error(ctxt->userData,
4267 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4268 node->name);
4269 return(-1);
4270 } else if (ret == 0) {
4271 ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4272 if (ctxt->error != NULL)
4273 ctxt->error(ctxt->userData,
4274 "Element %s content is not a simple type\n",
4275 node->name);
4276 return(-1);
4277 }
4278 /*
4279 * Validation Rule: Element Locally Valid (Type): 3.1.1
4280 */
4281 attr = node->properties;
4282 while (attr != NULL) {
4283 if ((attr->ns == NULL) ||
4284 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
4285 ((!xmlStrEqual(attr->name, BAD_CAST"type")) &&
4286 (!xmlStrEqual(attr->name, BAD_CAST"nil")) &&
4287 (!xmlStrEqual(attr->name, BAD_CAST"schemasLocation")) &&
4288 (!xmlStrEqual(attr->name, BAD_CAST"noNamespaceSchemaLocation")))) {
4289 ctxt->err = XML_SCHEMAS_ERR_INVALIDATTR;
4290 if (ctxt->error != NULL)
4291 ctxt->error(ctxt->userData,
4292 "Element %s: attribute %s should not be present\n",
4293 child->name, attr->name);
4294 return(ctxt->err);
4295 }
4296 }
4297
4298 ctxt->type = type->subtypes;
4299 ret = xmlSchemaValidateSimpleContent(ctxt, node);
4300 ctxt->type = type;
4301 return(ret);
4302}
4303
4304/**
4305 * xmlSchemaValidateElementType:
4306 * @ctxt: a schema validation context
4307 * @node: the top node.
4308 *
4309 * Validate the content of an element type.
4310 * Validation Rule: Element Locally Valid (Complex Type)
4311 *
4312 * Returns 0 if the element is schemas valid, a positive error code
4313 * number otherwise and -1 in case of internal or API error.
4314 */
4315static int
4316xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4317 xmlNodePtr child;
4318 xmlSchemaTypePtr type;
4319 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
4320 xmlSchemaElementPtr decl;
4321 int ret, attrBase;
4322
4323 oldregexp = ctxt->regexp;
4324
4325 child = ctxt->node;
4326 type = ctxt->type;
4327
4328 if ((ctxt == NULL) || (type == NULL)) {
4329 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4330 if (ctxt->error != NULL)
4331 ctxt->error(ctxt->userData,
4332 "Internal error: xmlSchemaValidateElementType\n",
4333 node->name);
4334 return(-1);
4335 }
4336 if (child == NULL) {
4337 if (type->minOccurs > 0) {
4338 ctxt->err = XML_SCHEMAS_ERR_MISSING;
4339 if (ctxt->error != NULL)
4340 ctxt->error(ctxt->userData,
4341 "Element %s: missing child %s\n",
4342 node->name, type->name);
4343 }
4344 return(ctxt->err);
4345 }
4346
4347 /*
4348 * Verify the element matches
4349 */
4350 if (!xmlStrEqual(child->name, type->name)) {
4351 ctxt->err = XML_SCHEMAS_ERR_WRONGELEM;
4352 if (ctxt->error != NULL)
4353 ctxt->error(ctxt->userData,
4354 "Element %s: missing child %s found %s\n",
4355 node->name, type->name, child->name);
4356 return(ctxt->err);
4357 }
4358 /*
4359 * Verify the attributes
4360 */
4361 attrBase = ctxt->attrBase;
4362 ctxt->attrBase = ctxt->attrNr;
4363 xmlSchemaRegisterAttributes(ctxt, child->properties);
4364 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
4365 /*
4366 * Verify the element content recursively
4367 */
4368 decl = (xmlSchemaElementPtr) type;
4369 oldregexp = ctxt->regexp;
4370 if (decl->contModel != NULL) {
4371 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
4372 (xmlRegExecCallbacks) xmlSchemaValidateCallback,
4373 ctxt);
4374#ifdef DEBUG_AUTOMATA
4375 xmlGenericError(xmlGenericErrorContext,
4376 "====> %s\n", node->name);
4377#endif
4378 }
4379 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr)type,
4380 type->subtypes);
4381
4382 if (decl->contModel != NULL) {
4383 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
4384#ifdef DEBUG_AUTOMATA
4385 xmlGenericError(xmlGenericErrorContext,
4386 "====> %s : %d\n", node->name, ret);
4387#endif
4388 if (ret == 0) {
Daniel Veillard8651f532002-04-17 09:06:27 +00004389 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
Daniel Veillard4255d502002-04-16 15:50:10 +00004390 if (ctxt->error != NULL)
4391 ctxt->error(ctxt->userData, "Element %s content check failed\n",
4392 node->name);
4393 } else if (ret < 0) {
Daniel Veillard8651f532002-04-17 09:06:27 +00004394 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
Daniel Veillard4255d502002-04-16 15:50:10 +00004395 if (ctxt->error != NULL)
4396 ctxt->error(ctxt->userData, "Element %s content check failure\n",
4397 node->name);
4398#ifdef DEBUG_CONTENT
4399 } else {
4400 xmlGenericError(xmlGenericErrorContext,
4401 "Element %s content check succeeded\n", node->name);
4402
4403#endif
4404 }
4405 xmlRegFreeExecCtxt(ctxt->regexp);
4406 }
4407 /*
4408 * Verify that all attributes were Schemas-validated
4409 */
4410 xmlSchemaCheckAttributes(ctxt, node);
4411 ctxt->attrNr = ctxt->attrBase;
4412 ctxt->attrBase = attrBase;
4413
4414 ctxt->regexp = oldregexp;
4415
4416 ctxt->node = child;
4417 ctxt->type = type;
4418 return(ctxt->err);
4419}
4420
4421/**
4422 * xmlSchemaValidateBasicType:
4423 * @ctxt: a schema validation context
4424 * @node: the top node.
4425 *
4426 * Validate the content of an element expected to be a basic type type
4427 *
4428 * Returns 0 if the element is schemas valid, a positive error code
4429 * number otherwise and -1 in case of internal or API error.
4430 */
4431static int
4432xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4433 int ret;
4434 xmlNodePtr child, cur;
4435 xmlSchemaTypePtr type;
4436 xmlChar *value; /* lexical representation */
4437
4438 child = ctxt->node;
4439 type = ctxt->type;
4440
4441 if ((ctxt == NULL) || (type == NULL)) {
4442 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4443 if (ctxt->error != NULL)
4444 ctxt->error(ctxt->userData,
4445 "Internal error: xmlSchemaValidateBasicType\n",
4446 node->name);
4447 return(-1);
4448 }
4449 /*
4450 * First check the content model of the node.
4451 */
4452 cur = child;
4453 while (cur != NULL) {
4454 switch (cur->type) {
4455 case XML_TEXT_NODE:
4456 case XML_CDATA_SECTION_NODE:
4457 case XML_PI_NODE:
4458 case XML_COMMENT_NODE:
4459 case XML_XINCLUDE_START:
4460 case XML_XINCLUDE_END:
4461 break;
4462 case XML_ENTITY_REF_NODE:
4463 case XML_ENTITY_NODE:
4464 TODO
4465 break;
4466 case XML_ELEMENT_NODE:
4467 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
4468 if (ctxt->error != NULL)
4469 ctxt->error(ctxt->userData,
4470 "Element %s: child %s should not be present\n",
4471 node->name, cur->name);
4472 return(ctxt->err);
4473 case XML_ATTRIBUTE_NODE:
4474 case XML_DOCUMENT_NODE:
4475 case XML_DOCUMENT_TYPE_NODE:
4476 case XML_DOCUMENT_FRAG_NODE:
4477 case XML_NOTATION_NODE:
4478 case XML_HTML_DOCUMENT_NODE:
4479 case XML_DTD_NODE:
4480 case XML_ELEMENT_DECL:
4481 case XML_ATTRIBUTE_DECL:
4482 case XML_ENTITY_DECL:
4483 case XML_NAMESPACE_DECL:
4484#ifdef LIBXML_DOCB_ENABLED
4485 case XML_DOCB_DOCUMENT_NODE:
4486#endif
4487 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
4488 if (ctxt->error != NULL)
4489 ctxt->error(ctxt->userData,
4490 "Element %s: node type %d unexpected here\n",
4491 node->name, cur->type);
4492 return(ctxt->err);
4493 }
4494 cur = cur->next;
4495 }
4496 if (child == NULL)
4497 value = NULL;
4498 else
4499 value = xmlNodeGetContent(child->parent);
4500
4501 if (ctxt->value != NULL) {
4502 xmlSchemaFreeValue(ctxt->value);
4503 ctxt->value = NULL;
4504 }
4505 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
4506 if (value != NULL)
4507 xmlFree(value);
4508 if (ret != 0) {
4509 ctxt->error(ctxt->userData,
4510 "Element %s: failed to validate basic type %s\n",
4511 node->name, type->name);
4512 }
4513 return(ret);
4514}
4515
4516/**
4517 * xmlSchemaValidateComplexType:
4518 * @ctxt: a schema validation context
4519 * @node: the top node.
4520 *
4521 * Validate the content of an element expected to be a complex type type
4522 * xmlschema-1.html#cvc-complex-type
4523 * Validation Rule: Element Locally Valid (Complex Type)
4524 *
4525 * Returns 0 if the element is schemas valid, a positive error code
4526 * number otherwise and -1 in case of internal or API error.
4527 */
4528static int
4529xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4530 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00004531 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004532 int ret;
4533
4534 child = ctxt->node;
4535 type = ctxt->type;
4536
Daniel Veillard4255d502002-04-16 15:50:10 +00004537 switch (type->contentType) {
4538 case XML_SCHEMA_CONTENT_EMPTY:
4539 if (child != NULL) {
4540 if (ctxt->error != NULL)
4541 ctxt->error(ctxt->userData,
4542 "Element %s is supposed to be empty\n",
4543 node->name);
4544 }
Daniel Veillarde19fc232002-04-22 16:01:24 +00004545 if (type->attributes != NULL) {
4546 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4547 }
4548 subtype = type->subtypes;
4549 while (subtype != NULL) {
4550 ctxt->type = subtype;
4551 xmlSchemaValidateComplexType(ctxt, node);
4552 subtype = subtype->next;
4553 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004554 break;
4555 case XML_SCHEMA_CONTENT_ELEMENTS:
4556 case XML_SCHEMA_CONTENT_MIXED:
4557 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4558 /*
4559 * Skip ignorable nodes in that context
4560 */
4561 child = xmlSchemaSkipIgnored(ctxt, type, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004562 while (child != NULL) {
4563 if (child->type == XML_ELEMENT_NODE) {
4564 ret = xmlRegExecPushString(ctxt->regexp,
4565 child->name, child);
4566#ifdef DEBUG_AUTOMATA
4567 if (ret < 0)
4568 xmlGenericError(xmlGenericErrorContext,
4569 " --> %s Error\n", child->name);
4570 else
4571 xmlGenericError(xmlGenericErrorContext,
4572 " --> %s\n", child->name);
4573#endif
4574 }
4575 child = child->next;
4576 /*
4577 * Skip ignorable nodes in that context
4578 */
4579 child = xmlSchemaSkipIgnored(ctxt, type, child);
4580 }
4581 break;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004582 case XML_SCHEMA_CONTENT_BASIC: {
4583 if (type->subtypes != NULL) {
4584 ctxt->type = type->subtypes;
4585 xmlSchemaValidateComplexType(ctxt, node);
4586 }
4587 if (type->baseType != NULL) {
4588 ctxt->type = type->baseType;
4589 xmlSchemaValidateBasicType(ctxt, node);
4590 }
4591 if (type->attributes != NULL) {
4592 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4593 }
4594 ctxt->type = type;
4595 break;
4596 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004597 default:
4598 TODO
4599 xmlGenericError(xmlGenericErrorContext,
4600 "unimplemented content type %d\n",
4601 type->contentType);
4602 }
4603 return(ctxt->err);
4604}
4605
4606/**
4607 * xmlSchemaValidateContent:
4608 * @ctxt: a schema validation context
4609 * @elem: an element
4610 * @type: the type declaration
4611 *
4612 * Validate the content of an element against the type.
4613 *
4614 * Returns 0 if the element is schemas valid, a positive error code
4615 * number otherwise and -1 in case of internal or API error.
4616 */
4617static int
4618xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4619 xmlNodePtr child;
4620 xmlSchemaTypePtr type;
4621
4622 child = ctxt->node;
4623 type = ctxt->type;
4624
Daniel Veillarde19fc232002-04-22 16:01:24 +00004625 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4626
Daniel Veillard4255d502002-04-16 15:50:10 +00004627 switch (type->type) {
4628 case XML_SCHEMA_TYPE_ANY:
4629 /* Any type will do it, fine */
4630 TODO /* handle recursivity */
4631 break;
4632 case XML_SCHEMA_TYPE_COMPLEX:
4633 xmlSchemaValidateComplexType(ctxt, node);
4634 break;
4635 case XML_SCHEMA_TYPE_ELEMENT: {
4636 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
4637 /*
4638 * Handle element reference here
4639 */
4640 if (decl->ref != NULL) {
4641 if (decl->refDecl == NULL) {
4642 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4643 if (ctxt->error != NULL)
4644 ctxt->error(ctxt->userData,
4645 "Internal error: element reference %s not resolved\n",
4646 decl->ref);
4647 return(-1);
4648 }
4649 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
4650 decl = decl->refDecl;
4651 }
4652 xmlSchemaValidateElementType(ctxt, node);
4653 ctxt->type = type;
4654 break;
4655 }
4656 case XML_SCHEMA_TYPE_BASIC:
4657 xmlSchemaValidateBasicType(ctxt, node);
4658 break;
4659 case XML_SCHEMA_TYPE_FACET:
4660 TODO
4661 break;
4662 case XML_SCHEMA_TYPE_SIMPLE:
4663 xmlSchemaValidateSimpleType(ctxt, node);
4664 break;
4665 case XML_SCHEMA_TYPE_SEQUENCE:
4666 TODO
4667 break;
4668 case XML_SCHEMA_TYPE_CHOICE:
4669 TODO
4670 break;
4671 case XML_SCHEMA_TYPE_ALL:
4672 TODO
4673 break;
4674 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
4675 TODO
4676 break;
4677 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4678 TODO
4679 break;
4680 case XML_SCHEMA_TYPE_UR:
4681 TODO
4682 break;
4683 case XML_SCHEMA_TYPE_RESTRICTION:
4684 /*xmlSchemaValidateRestrictionType(ctxt, node); */
4685 TODO
4686 break;
4687 case XML_SCHEMA_TYPE_EXTENSION:
4688 TODO
4689 break;
4690 case XML_SCHEMA_TYPE_ATTRIBUTE:
4691 TODO
4692 break;
4693 case XML_SCHEMA_TYPE_GROUP:
4694 TODO
4695 break;
4696 case XML_SCHEMA_TYPE_NOTATION:
4697 TODO
4698 break;
4699 case XML_SCHEMA_TYPE_LIST:
4700 TODO
4701 break;
4702 case XML_SCHEMA_TYPE_UNION:
4703 TODO
4704 break;
4705 case XML_SCHEMA_FACET_MININCLUSIVE:
4706 TODO
4707 break;
4708 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4709 TODO
4710 break;
4711 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4712 TODO
4713 break;
4714 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4715 TODO
4716 break;
4717 case XML_SCHEMA_FACET_TOTALDIGITS:
4718 TODO
4719 break;
4720 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4721 TODO
4722 break;
4723 case XML_SCHEMA_FACET_PATTERN:
4724 TODO
4725 break;
4726 case XML_SCHEMA_FACET_ENUMERATION:
4727 TODO
4728 break;
4729 case XML_SCHEMA_FACET_WHITESPACE:
4730 TODO
4731 break;
4732 case XML_SCHEMA_FACET_LENGTH:
4733 TODO
4734 break;
4735 case XML_SCHEMA_FACET_MAXLENGTH:
4736 TODO
4737 break;
4738 case XML_SCHEMA_FACET_MINLENGTH:
4739 TODO
4740 break;
4741 }
4742 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4743
4744 if (ctxt->node == NULL)
4745 return(ctxt->err);
4746 ctxt->node = ctxt->node->next;
4747 ctxt->type = type->next;
4748 return(ctxt->err);
4749}
4750
4751/**
4752 * xmlSchemaValidateType:
4753 * @ctxt: a schema validation context
4754 * @elem: an element
4755 * @type: the list of type declarations
4756 *
4757 * Validate the content of an element against the types.
4758 *
4759 * Returns 0 if the element is schemas valid, a positive error code
4760 * number otherwise and -1 in case of internal or API error.
4761 */
4762static int
4763xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
4764 xmlSchemaElementPtr elemDecl,
4765 xmlSchemaTypePtr type) {
4766 xmlChar *nil;
4767
4768 if ((elem->content == NULL) || (type == NULL) || (elemDecl == NULL))
4769 return(0);
4770 /*
4771 * 3.3.4 : 2
4772 */
4773 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
4774 ctxt->err = XML_SCHEMAS_ERR_ISABSTRACT;
4775 if (ctxt->error != NULL)
4776 ctxt->error(ctxt->userData, "Element %s is abstract\n", elem->name);
4777 return(ctxt->err);
4778 }
4779 /*
4780 * 3.3.4: 3
4781 */
4782 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
4783 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
4784 /* 3.3.4: 3.2 */
4785 if (xmlStrEqual(nil, BAD_CAST "true")) {
4786 if (elem->children != NULL) {
4787 ctxt->err = XML_SCHEMAS_ERR_NOTEMPTY;
4788 if (ctxt->error != NULL)
4789 ctxt->error(ctxt->userData, "Element %s is not empty\n",
4790 elem->name);
4791 return(ctxt->err);
4792 }
4793 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
4794 (elemDecl->value != NULL)) {
4795 ctxt->err = XML_SCHEMAS_ERR_HAVEDEFAULT;
4796 if (ctxt->error != NULL)
4797 ctxt->error(ctxt->userData,
4798 "Empty element %s cannot get a fixed value\n",
4799 elem->name);
4800 return(ctxt->err);
4801 }
4802 }
4803 } else {
4804 /* 3.3.4: 3.1 */
4805 if (nil != NULL) {
4806 ctxt->err = XML_SCHEMAS_ERR_NOTNILLABLE;
4807 if (ctxt->error != NULL)
4808 ctxt->error(ctxt->userData,
4809 "Element %s with xs:nil but not nillable\n",
4810 elem->name);
4811 xmlFree(nil);
4812 return(ctxt->err);
4813 }
4814 }
4815
4816 /* TODO 3.3.4: 4 if the element carries xs:type*/
4817
4818 ctxt->type = elemDecl->subtypes;
4819 ctxt->node = elem->children;
4820 xmlSchemaValidateContent(ctxt, elem);
4821 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
4822
4823 return(ctxt->err);
4824}
4825
4826
4827/**
4828 * xmlSchemaValidateAttributes:
4829 * @ctxt: a schema validation context
4830 * @elem: an element
4831 * @attributes: the list of attribute declarations
4832 *
4833 * Validate the attributes of an element.
4834 *
4835 * Returns 0 if the element is schemas valid, a positive error code
4836 * number otherwise and -1 in case of internal or API error.
4837 */
4838static int
4839xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
4840 xmlSchemaAttributePtr attributes) {
4841 int i, ret;
4842 xmlAttrPtr attr;
4843 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004844 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004845
4846 if (attributes == NULL)
4847 return(0);
4848 while (attributes != NULL) {
Daniel Veillard13e04c62002-04-23 17:51:29 +00004849 /*
4850 * Handle attribute groups
4851 */
4852 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
4853 group = (xmlSchemaAttributeGroupPtr) attributes;
4854 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
4855 attributes = group->next;
4856 continue;
4857 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004858 for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
4859 attr = ctxt->attr[i].attr;
4860 if (attr == NULL)
4861 continue;
4862 if (!xmlStrEqual(attr->name, attributes->name))
4863 continue;
4864 /*
4865 * TODO: handle the mess about namespaces here.
4866 */
4867 if ((attr->ns != NULL) /* || (attributes->ns != NULL) */) {
4868 TODO
4869 }
4870 if (attributes->subtypes == NULL) {
4871 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4872 if (ctxt->error != NULL)
4873 ctxt->error(ctxt->userData,
4874 "Internal error: attribute %s type not resolved\n",
4875 attr->name);
4876 continue;
4877 }
4878 value = xmlNodeListGetString(elem->doc, attr->children, 1);
4879 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
Daniel Veillard13e04c62002-04-23 17:51:29 +00004880 value);
Daniel Veillard4255d502002-04-16 15:50:10 +00004881 if (ret != 0) {
4882 ctxt->err = XML_SCHEMAS_ERR_ATTRINVALID;
4883 if (ctxt->error != NULL)
4884 ctxt->error(ctxt->userData,
4885 "attribute %s on %s does not match type\n",
4886 attr->name, elem->name);
4887 } else {
4888 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
4889 }
4890 if (value != NULL) {
4891 xmlFree(value);
4892 }
4893 }
4894 attributes = attributes->next;
4895 }
4896 return(ctxt->err);
4897}
4898
4899/**
4900 * xmlSchemaValidateElement:
4901 * @ctxt: a schema validation context
4902 * @elem: an element
4903 *
4904 * Validate an element in a tree
4905 *
4906 * Returns 0 if the element is schemas valid, a positive error code
4907 * number otherwise and -1 in case of internal or API error.
4908 */
4909static int
4910xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem) {
4911 xmlSchemaElementPtr elemDecl;
4912 int ret, attrBase;
4913
4914 if (elem->ns != NULL)
4915 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
4916 elem->name, elem->ns->href, NULL);
4917 else
4918 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
4919 elem->name, NULL, NULL);
4920 /*
4921 * 3.3.4 : 1
4922 */
4923 if (elemDecl == NULL) {
4924 ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
4925 if (ctxt->error != NULL)
4926 ctxt->error(ctxt->userData, "Element %s not declared\n",
4927 elem->name);
4928 return(ctxt->err);
4929 }
4930 if (elemDecl->subtypes == NULL) {
4931 ctxt->err = XML_SCHEMAS_ERR_NOTYPE;
4932 if (ctxt->error != NULL)
4933 ctxt->error(ctxt->userData, "Element %s has no type\n",
4934 elem->name);
4935 return(ctxt->err);
4936 }
4937 /*
4938 * Verify the attributes
4939 */
4940 attrBase = ctxt->attrBase;
4941 ctxt->attrBase = ctxt->attrNr;
4942 xmlSchemaRegisterAttributes(ctxt, elem->properties);
4943 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
4944 /*
4945 * Verify the element content recursively
4946 */
4947 if (elemDecl->contModel != NULL) {
4948 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
4949 (xmlRegExecCallbacks) xmlSchemaValidateCallback,
4950 ctxt);
4951#ifdef DEBUG_AUTOMATA
4952 xmlGenericError(xmlGenericErrorContext,
4953 "====> %s\n", elem->name);
4954#endif
4955 }
4956 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004957 if (elemDecl->contModel != NULL) {
4958 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004959#ifdef DEBUG_AUTOMATA
Daniel Veillard4255d502002-04-16 15:50:10 +00004960 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004961 "====> %s : %d\n", elem->name, ret);
4962#endif
4963 if (ret == 0) {
4964 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
4965 if (ctxt->error != NULL)
4966 ctxt->error(ctxt->userData, "Element %s content check failed\n",
4967 elem->name);
4968 } else if (ret < 0) {
4969 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
4970 if (ctxt->error != NULL)
4971 ctxt->error(ctxt->userData, "Element %s content check failed\n",
4972 elem->name);
4973#ifdef DEBUG_CONTENT
4974 } else {
4975 xmlGenericError(xmlGenericErrorContext,
4976 "Element %s content check succeeded\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004977
4978#endif
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004979 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004980 xmlRegFreeExecCtxt(ctxt->regexp);
4981 }
4982 /*
4983 * Verify that all attributes were Schemas-validated
4984 */
4985 xmlSchemaCheckAttributes(ctxt, elem);
4986 ctxt->attrNr = ctxt->attrBase;
4987 ctxt->attrBase = attrBase;
4988
4989 return(ctxt->err);
4990}
4991
4992/**
4993 * xmlSchemaValidateDocument:
4994 * @ctxt: a schema validation context
4995 * @doc: a parsed document tree
4996 *
4997 * Validate a document tree in memory.
4998 *
4999 * Returns 0 if the document is schemas valid, a positive error code
5000 * number otherwise and -1 in case of internal or API error.
5001 */
5002static int
5003xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5004 xmlNodePtr root;
5005 xmlSchemaElementPtr elemDecl;
5006
5007 root = xmlDocGetRootElement(doc);
5008 if (root == NULL) {
5009 ctxt->err = XML_SCHEMAS_ERR_NOROOT;
5010 if (ctxt->error != NULL)
5011 ctxt->error(ctxt->userData, "document has no root\n");
5012 return(ctxt->err);
5013 }
5014 if (root->ns != NULL)
5015 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5016 root->name, root->ns->href, NULL);
5017 else
5018 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5019 root->name, NULL, NULL);
5020 if (elemDecl == NULL) {
5021 ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
5022 if (ctxt->error != NULL)
5023 ctxt->error(ctxt->userData, "Element %s not declared\n",
5024 root->name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005025 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005026 ctxt->err = XML_SCHEMAS_ERR_NOTTOPLEVEL;
5027 if (ctxt->error != NULL)
5028 ctxt->error(ctxt->userData, "Root element %s not toplevel\n",
5029 root->name);
5030 }
5031 /*
5032 * Okay, start the recursive validation
5033 */
5034 xmlSchemaValidateElement(ctxt, root);
5035
5036 return(ctxt->err);
5037}
5038
5039/************************************************************************
5040 * *
5041 * SAX Validation code *
5042 * *
5043 ************************************************************************/
5044
5045/************************************************************************
5046 * *
5047 * Validation interfaces *
5048 * *
5049 ************************************************************************/
5050
5051/**
5052 * xmlSchemaNewValidCtxt:
5053 * @schema: a precompiled XML Schemas
5054 *
5055 * Create an XML Schemas validation context based on the given schema
5056 *
5057 * Returns the validation context or NULL in case of error
5058 */
5059xmlSchemaValidCtxtPtr
5060xmlSchemaNewValidCtxt(xmlSchemaPtr schema) {
5061 xmlSchemaValidCtxtPtr ret;
5062
5063 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
5064 if (ret == NULL) {
5065 xmlGenericError(xmlGenericErrorContext,
5066 "Failed to allocate new schama validation context\n");
5067 return (NULL);
5068 }
5069 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
5070 ret->schema = schema;
5071 ret->attrNr = 0;
5072 ret->attrMax = 10;
5073 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
5074 sizeof(xmlSchemaAttrState));
5075 if (ret->attr == NULL) {
5076 free(ret);
5077 return(NULL);
5078 }
5079 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
5080 return (ret);
5081}
5082
5083/**
5084 * xmlSchemaFreeValidCtxt:
5085 * @ctxt: the schema validation context
5086 *
5087 * Free the resources associated to the schema validation context
5088 */
5089void
5090xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) {
5091 if (ctxt == NULL)
5092 return;
5093 if (ctxt->attr != NULL)
5094 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00005095 if (ctxt->value != NULL)
5096 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005097 xmlFree(ctxt);
5098}
5099
5100/**
5101 * xmlSchemaSetValidErrors:
5102 * @ctxt: a schema validation context
5103 * @err: the error function
5104 * @warn: the warning function
5105 * @ctxt: the functions context
5106 *
5107 * Set the error and warning callback informations
5108 */
5109void
5110xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
5111 xmlSchemaValidityErrorFunc err,
5112 xmlSchemaValidityWarningFunc warn, void *ctx) {
5113 if (ctxt == NULL)
5114 return;
5115 ctxt->error = err;
5116 ctxt->warning = warn;
5117 ctxt->userData = ctx;
5118}
5119
5120/**
5121 * xmlSchemaValidateDoc:
5122 * @ctxt: a schema validation context
5123 * @doc: a parsed document tree
5124 *
5125 * Validate a document tree in memory.
5126 *
5127 * Returns 0 if the document is schemas valid, a positive error code
5128 * number otherwise and -1 in case of internal or API error.
5129 */
5130int
5131xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5132 int ret;
5133
5134 if ((ctxt == NULL) || (doc == NULL))
5135 return(-1);
5136
5137 ctxt->doc = doc;
5138 ret = xmlSchemaValidateDocument(ctxt, doc);
5139 return(ret);
5140}
5141
5142/**
5143 * xmlSchemaValidateStream:
5144 * @ctxt: a schema validation context
5145 * @input: the input to use for reading the data
5146 * @enc: an optional encoding information
5147 * @sax: a SAX handler for the resulting events
5148 * @user_data: the context to provide to the SAX handler.
5149 *
5150 * Validate a document tree in memory.
5151 *
5152 * Returns 0 if the document is schemas valid, a positive error code
5153 * number otherwise and -1 in case of internal or API error.
5154 */
5155int
5156xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
5157 xmlParserInputBufferPtr input, xmlCharEncoding enc,
5158 xmlSAXHandlerPtr sax, void *user_data) {
5159 if ((ctxt == NULL) || (input == NULL))
5160 return(-1);
5161 ctxt->input = input;
5162 ctxt->enc = enc;
5163 ctxt->sax = sax;
5164 ctxt->user_data = user_data;
5165 TODO
5166 return(0);
5167}
5168
5169#endif /* LIBXML_SCHEMAS_ENABLED */