blob: d8a02255533d849d7f895ef9c6fb836fbda0fed2 [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")) {
Daniel Veillard10b6da42002-05-18 07:55:20 +00002794 /* xmlSchemaParseImport(ctxt, schema, child);*/
Daniel Veillard4255d502002-04-16 15:50:10 +00002795 TODO
2796 } else if (IS_SCHEMA(child, "redefine")) {
2797 TODO
2798 }
2799 child = child->next;
2800 }
2801 while (child != NULL) {
2802 if (IS_SCHEMA(child, "complexType")) {
2803 xmlSchemaParseComplexType(ctxt, schema, child);
2804 child = child->next;
2805 } else if (IS_SCHEMA(child, "simpleType")) {
2806 xmlSchemaParseSimpleType(ctxt, schema, child);
2807 child = child->next;
2808 } else if (IS_SCHEMA(child, "element")) {
2809 xmlSchemaParseElement(ctxt, schema, child, 1);
2810 child = child->next;
2811 } else if (IS_SCHEMA(child, "attribute")) {
2812 xmlSchemaParseAttribute(ctxt, schema, child);
2813 child = child->next;
2814 } else if (IS_SCHEMA(child, "attributeGroup")) {
2815 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2816 child = child->next;
2817 } else if (IS_SCHEMA(child, "group")) {
2818 xmlSchemaParseGroup(ctxt, schema, child);
2819 child = child->next;
2820 } else if (IS_SCHEMA(child, "notation")) {
2821 xmlSchemaParseNotation(ctxt, schema, child);
2822 child = child->next;
2823 } else {
2824 xmlSchemaErrorContext(ctxt, schema, node, child);
2825 if ((ctxt != NULL) && (ctxt->error != NULL))
2826 ctxt->error(ctxt->userData,
2827 "Schemas: unexpected element %s here \n",
2828 child->name);
2829 child = child->next;
2830 }
2831 while (IS_SCHEMA(child, "annotation")) {
2832 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2833 if (schema->annot == NULL)
2834 schema->annot = annot;
2835 else
2836 xmlSchemaFreeAnnot(annot);
2837 child = child->next;
2838 }
2839 }
2840 }
2841#ifdef DEBUG
2842 if (schema == NULL)
2843 xmlGenericError(xmlGenericErrorContext,
2844 "xmlSchemaParse() failed\n");
2845#endif
2846
2847 return (schema);
2848}
2849
2850/************************************************************************
2851 * *
2852 * Validating using Schemas *
2853 * *
2854 ************************************************************************/
2855
2856/************************************************************************
2857 * *
2858 * Reading/Writing Schemas *
2859 * *
2860 ************************************************************************/
2861
2862/**
2863 * xmlSchemaNewParserCtxt:
2864 * @URL: the location of the schema
2865 *
2866 * Create an XML Schemas parse context for that file/resource expected
2867 * to contain an XML Schemas file.
2868 *
2869 * Returns the parser context or NULL in case of error
2870 */
2871xmlSchemaParserCtxtPtr
2872xmlSchemaNewParserCtxt(const char *URL) {
2873 xmlSchemaParserCtxtPtr ret;
2874
2875 if (URL == NULL)
2876 return(NULL);
2877
2878 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
2879 if (ret == NULL) {
2880 xmlGenericError(xmlGenericErrorContext,
2881 "Failed to allocate new schama parser context for %s\n", URL);
2882 return (NULL);
2883 }
2884 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
2885 ret->URL = xmlStrdup((const xmlChar *)URL);
2886 return (ret);
2887}
2888
2889/**
2890 * xmlSchemaFreeParserCtxt:
2891 * @ctxt: the schema parser context
2892 *
2893 * Free the resources associated to the schema parser context
2894 */
2895void
2896xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) {
2897 if (ctxt == NULL)
2898 return;
2899 if (ctxt->URL != NULL)
2900 xmlFree(ctxt->URL);
2901 xmlFree(ctxt);
2902}
2903
2904/************************************************************************
2905 * *
2906 * Building the content models *
2907 * *
2908 ************************************************************************/
2909/**
2910 * xmlSchemaBuildAContentModel:
2911 * @type: the schema type definition
2912 * @ctxt: the schema parser context
2913 * @name: the element name whose content is being built
2914 *
2915 * Generate the automata sequence needed for that type
2916 */
2917static void
2918xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
2919 xmlSchemaParserCtxtPtr ctxt,
2920 const xmlChar *name) {
2921 if (type == NULL) {
2922 xmlGenericError(xmlGenericErrorContext,
2923 "Found unexpected type = NULL in %s content model\n",
2924 name);
2925 return;
2926 }
2927 switch (type->type) {
2928 case XML_SCHEMA_TYPE_ANY:
2929 /* TODO : handle the namespace too */
2930 /* TODO : make that a specific transition type */
2931 TODO
2932 ctxt->state = xmlAutomataNewTransition(ctxt->am, ctxt->state,
2933 NULL, BAD_CAST "*", NULL);
2934 break;
2935 case XML_SCHEMA_TYPE_ELEMENT: {
2936 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
2937 /* TODO : handle the namespace too */
2938 xmlAutomataStatePtr oldstate = ctxt->state;
2939 if (elem->maxOccurs >= UNBOUNDED) {
2940 if (elem->refDecl != NULL) {
2941 xmlSchemaBuildAContentModel(
2942 (xmlSchemaTypePtr) elem->refDecl,
2943 ctxt, elem->refDecl->name);
2944 } else {
2945 ctxt->state = xmlAutomataNewTransition(ctxt->am,
2946 ctxt->state, NULL, elem->name, type);
2947 }
2948 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
2949 if (elem->minOccurs == 0) {
2950 /* basically an elem* */
2951 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
2952 }
2953 } else if (elem->maxOccurs > 1) {
2954 if (elem->refDecl != NULL) {
2955 TODO
2956 xmlSchemaBuildAContentModel(
2957 (xmlSchemaTypePtr) elem->refDecl,
2958 ctxt, elem->refDecl->name);
2959 } else {
2960 ctxt->state = xmlAutomataNewCountTrans(ctxt->am,
2961 ctxt->state, NULL, elem->name,
2962 elem->minOccurs, elem->maxOccurs, type);
2963 }
2964 } else {
2965 if (elem->refDecl != NULL) {
2966 xmlSchemaBuildAContentModel(
2967 (xmlSchemaTypePtr) elem->refDecl,
2968 ctxt, elem->refDecl->name);
2969 } else {
2970 ctxt->state = xmlAutomataNewTransition(ctxt->am,
2971 ctxt->state, NULL, elem->name, type);
2972 }
2973 if (elem->minOccurs == 0) {
2974 /* basically an elem? */
2975 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
2976 }
2977 }
2978 break;
2979 }
2980 case XML_SCHEMA_TYPE_SEQUENCE: {
2981 xmlSchemaTypePtr subtypes;
2982
2983 /*
2984 * Simply iterate over the subtypes
2985 */
2986 subtypes = type->subtypes;
2987 while (subtypes != NULL) {
2988 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
2989 subtypes = subtypes->next;
2990 }
2991 break;
2992 }
2993 case XML_SCHEMA_TYPE_CHOICE: {
2994 xmlSchemaTypePtr subtypes;
2995 xmlAutomataStatePtr start, end;
2996
2997 start = ctxt->state;
2998 end = xmlAutomataNewState(ctxt->am);
2999
3000 /*
3001 * iterate over the subtypes and remerge the end with an
3002 * epsilon transition
3003 */
Daniel Veillardb509f152002-04-17 16:28:10 +00003004 if (type->maxOccurs == 1) {
3005 subtypes = type->subtypes;
3006 while (subtypes != NULL) {
3007 ctxt->state = start;
3008 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3009 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
3010 subtypes = subtypes->next;
3011 }
3012 } else {
3013 int counter;
3014 xmlAutomataStatePtr hop;
3015
3016 /*
3017 * use a counter to keep track of the number of transtions
3018 * which went through the choice.
3019 */
3020 if (type->minOccurs < 1) {
3021 counter = xmlAutomataNewCounter(ctxt->am, 0,
3022 type->maxOccurs - 1);
3023 } else {
3024 counter = xmlAutomataNewCounter(ctxt->am,
3025 type->minOccurs - 1, type->maxOccurs - 1);
3026 }
3027 hop = xmlAutomataNewState(ctxt->am);
3028
3029 subtypes = type->subtypes;
3030 while (subtypes != NULL) {
3031 ctxt->state = start;
3032 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3033 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
3034 subtypes = subtypes->next;
3035 }
3036 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
3037 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
3038 }
3039 if (type->minOccurs == 0) {
3040 xmlAutomataNewEpsilon(ctxt->am, start, end);
Daniel Veillard4255d502002-04-16 15:50:10 +00003041 }
3042 ctxt->state = end;
3043 break;
3044 }
3045 case XML_SCHEMA_TYPE_ALL: {
Daniel Veillard7646b182002-04-20 06:41:40 +00003046 xmlAutomataStatePtr start;
3047 xmlSchemaTypePtr subtypes;
3048 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard441bc322002-04-20 17:38:48 +00003049 int lax;
Daniel Veillard7646b182002-04-20 06:41:40 +00003050
3051 subtypes = type->subtypes;
3052 if (subtypes == NULL)
3053 break;
3054 start = ctxt->state;
3055 while (subtypes != NULL) {
3056 ctxt->state = start;
3057 elem = (xmlSchemaElementPtr) subtypes;
3058
3059 /* TODO : handle the namespace too */
3060 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state, ctxt->state,
3061 elem->name, elem->minOccurs, elem->maxOccurs,
3062 subtypes);
3063 subtypes = subtypes->next;
3064 }
Daniel Veillard441bc322002-04-20 17:38:48 +00003065 lax = type->minOccurs == 0;
3066 ctxt->state = xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
3067 lax);
Daniel Veillard4255d502002-04-16 15:50:10 +00003068 break;
3069 }
3070 case XML_SCHEMA_TYPE_RESTRICTION:
Daniel Veillardb4398962002-04-19 07:01:55 +00003071 if (type->subtypes != NULL)
Daniel Veillard6231e842002-04-18 11:54:04 +00003072 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3073 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003074 case XML_SCHEMA_TYPE_EXTENSION:
Daniel Veillard6231e842002-04-18 11:54:04 +00003075 if (type->baseType != NULL) {
3076 xmlSchemaTypePtr subtypes;
3077
3078 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
3079 subtypes = type->subtypes;
3080 while (subtypes != NULL) {
3081 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3082 subtypes = subtypes->next;
3083 }
3084 } else if (type->subtypes != NULL)
3085 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3086 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003087 case XML_SCHEMA_TYPE_GROUP:
3088 case XML_SCHEMA_TYPE_COMPLEX:
3089 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
3090 if (type->subtypes != NULL)
3091 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3092 break;
3093 default:
3094 xmlGenericError(xmlGenericErrorContext,
3095 "Found unexpected type %d in %s content model\n",
3096 type->type, name);
3097 return;
3098 }
3099}
3100/**
3101 * xmlSchemaBuildContentModel:
3102 * @typeDecl: the schema type definition
3103 * @ctxt: the schema parser context
3104 *
3105 * Fixes the content model of the element.
3106 */
3107static void
3108xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
3109 xmlSchemaParserCtxtPtr ctxt,
3110 const xmlChar *name) {
3111 xmlAutomataStatePtr start;
3112
Daniel Veillard4255d502002-04-16 15:50:10 +00003113 if (elem->contModel != NULL)
3114 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003115 if (elem->subtypes == NULL) {
3116 elem->contentType = XML_SCHEMA_CONTENT_ANY;
Daniel Veillard4255d502002-04-16 15:50:10 +00003117 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003118 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003119 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
3120 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003121 if (elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC)
3122 return;
3123
3124#ifdef DEBUG_CONTENT
3125 xmlGenericError(xmlGenericErrorContext,
3126 "Building content model for %s\n", name);
3127#endif
3128
Daniel Veillard4255d502002-04-16 15:50:10 +00003129 ctxt->am = xmlNewAutomata();
3130 if (ctxt->am == NULL) {
3131 xmlGenericError(xmlGenericErrorContext,
3132 "Cannot create automata for elem %s\n", name);
3133 return;
3134 }
3135 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3136 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3137 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillarde19fc232002-04-22 16:01:24 +00003138 if (!xmlAutomataIsDeterminist(ctxt->am)) {
3139 xmlGenericError(xmlGenericErrorContext,
3140 "Content model of %s is not determinist:\n", name);
3141 elem->contModel = xmlAutomataCompile(ctxt->am);
3142 ctxt->err = XML_SCHEMAS_ERR_NOTDETERMINIST;
3143 } else {
3144 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillard4255d502002-04-16 15:50:10 +00003145#ifdef DEBUG_CONTENT
Daniel Veillarde19fc232002-04-22 16:01:24 +00003146 xmlGenericError(xmlGenericErrorContext,
3147 "Content model of %s:\n", name);
3148 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003149#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00003150 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003151 ctxt->state = NULL;
3152 xmlFreeAutomata(ctxt->am);
3153 ctxt->am = NULL;
3154}
3155
3156/**
3157 * xmlSchemaRefFixupCallback:
3158 * @elem: the schema element context
3159 * @ctxt: the schema parser context
3160 *
3161 * Free the resources associated to the schema parser context
3162 */
3163static void
3164xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
3165 xmlSchemaParserCtxtPtr ctxt,
3166 const xmlChar *name,
3167 ATTRIBUTE_UNUSED const xmlChar *context,
3168 ATTRIBUTE_UNUSED const xmlChar *namespace)
3169{
3170 if ((ctxt == NULL) || (elem == NULL))
3171 return;
3172 if (elem->ref != NULL) {
3173 xmlSchemaElementPtr elemDecl;
3174
3175 if (elem->subtypes != NULL) {
3176 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3177 if ((ctxt != NULL) && (ctxt->error != NULL))
3178 ctxt->error(ctxt->userData,
3179 "Schemas: element %s have both ref and subtype\n",
3180 name);
3181 return;
3182 }
3183 elemDecl = xmlHashLookup2(ctxt->schema->elemDecl,
3184 elem->ref, elem->refNs);
3185
3186 if (elemDecl == NULL) {
3187 if ((ctxt != NULL) && (ctxt->error != NULL))
3188 ctxt->error(ctxt->userData,
3189 "Schemas: element %s ref to %s not found\n",
3190 name, elem->ref);
3191 return;
3192 }
3193 elem->refDecl = elemDecl;
3194 } else if (elem->namedType != NULL) {
3195 xmlSchemaTypePtr typeDecl;
3196
3197 if (elem->subtypes != NULL) {
3198 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3199 if ((ctxt != NULL) && (ctxt->error != NULL))
3200 ctxt->error(ctxt->userData,
3201 "Schemas: element %s have both type and subtype\n",
3202 name);
3203 return;
3204 }
3205 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3206 elem->namedTypeNs);
3207
3208 if (typeDecl == NULL) {
3209 if ((ctxt != NULL) && (ctxt->error != NULL))
3210 ctxt->error(ctxt->userData,
3211 "Schemas: element %s type %s not found\n",
3212 name, elem->namedType);
3213 return;
3214 }
3215 elem->subtypes = typeDecl;
3216 }
3217}
3218
3219/**
3220 * xmlSchemaTypeFixup:
3221 * @typeDecl: the schema type definition
3222 * @ctxt: the schema parser context
3223 *
3224 * Fixes the content model of the type.
3225 */
3226static void
3227xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
3228 xmlSchemaParserCtxtPtr ctxt,
3229 const xmlChar *name)
3230{
3231 if (name == NULL)
3232 name = typeDecl->name;
3233 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
3234 switch (typeDecl->type) {
3235 case XML_SCHEMA_TYPE_SIMPLE_CONTENT: {
3236 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3237 typeDecl->contentType = typeDecl->subtypes->contentType;
3238 break;
3239 }
3240 case XML_SCHEMA_TYPE_RESTRICTION: {
3241 if (typeDecl->subtypes != NULL)
3242 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3243
3244 if (typeDecl->base != NULL) {
3245 xmlSchemaTypePtr baseType;
3246
3247 baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3248 typeDecl->baseNs);
3249 if (baseType == NULL) {
3250 if ((ctxt != NULL) && (ctxt->error != NULL))
3251 ctxt->error(ctxt->userData,
3252 "Schemas: type %s base type %s not found\n",
3253 name, typeDecl->base);
3254 }
3255 typeDecl->baseType = baseType;
3256 }
3257 if (typeDecl->subtypes == NULL)
3258 /* 1.1.1 */
3259 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3260 else if ((typeDecl->subtypes->subtypes == NULL) &&
3261 ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3262 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3263 /* 1.1.2 */
3264 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3265 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3266 (typeDecl->subtypes->subtypes == NULL))
3267 /* 1.1.3 */
3268 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3269 else {
3270 /* 1.2 and 2.X are applied at the other layer */
3271 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3272 }
3273 break;
3274 }
3275 case XML_SCHEMA_TYPE_EXTENSION: {
3276 xmlSchemaContentType explicitContentType;
3277 xmlSchemaTypePtr base;
3278
3279 if (typeDecl->base != NULL) {
3280 xmlSchemaTypePtr baseType;
3281
3282 baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3283 typeDecl->baseNs);
3284 if (baseType == NULL) {
3285 if ((ctxt != NULL) && (ctxt->error != NULL))
3286 ctxt->error(ctxt->userData,
3287 "Schemas: type %s base type %s not found\n",
3288 name, typeDecl->base);
3289 }
3290 typeDecl->baseType = baseType;
3291 }
3292 if (typeDecl->subtypes != NULL)
3293 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3294
Daniel Veillard8651f532002-04-17 09:06:27 +00003295 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillard4255d502002-04-16 15:50:10 +00003296 if (typeDecl->subtypes == NULL)
3297 /* 1.1.1 */
3298 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3299 else if ((typeDecl->subtypes->subtypes == NULL) &&
3300 ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3301 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3302 /* 1.1.2 */
3303 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3304 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3305 (typeDecl->subtypes->subtypes == NULL))
3306 /* 1.1.3 */
3307 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3308
3309 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3310 typeDecl->baseNs);
3311 if (base == NULL) {
3312 xmlSchemaErrorContext(ctxt, NULL, typeDecl->node, NULL);
3313 if ((ctxt != NULL) && (ctxt->error != NULL))
3314 ctxt->error(ctxt->userData,
3315 "Schemas: base type %s of type %s not found\n",
3316 typeDecl->base, name);
3317 return;
3318 }
3319 xmlSchemaTypeFixup(base, ctxt, NULL);
3320 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
3321 /* 2.1 */
3322 typeDecl->contentType = base->contentType;
3323 } else if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
3324 /* 2.2 imbitable ! */
3325 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3326 } else {
3327 /* 2.3 imbitable pareil ! */
3328 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3329 }
3330 break;
3331 }
3332 case XML_SCHEMA_TYPE_COMPLEX: {
3333 if (typeDecl->subtypes == NULL) {
3334 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3335 } else {
3336 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3337 typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3338 else {
3339 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3340 typeDecl->contentType = typeDecl->subtypes->contentType;
3341 }
3342 }
3343 break;
3344 }
3345 case XML_SCHEMA_TYPE_COMPLEX_CONTENT: {
3346 if (typeDecl->subtypes == NULL) {
3347 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3348 } else {
3349 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3350 typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3351 else {
3352 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3353 typeDecl->contentType = typeDecl->subtypes->contentType;
3354 }
3355 }
3356 break;
3357 }
3358 case XML_SCHEMA_TYPE_SEQUENCE:
3359 case XML_SCHEMA_TYPE_GROUP:
3360 case XML_SCHEMA_TYPE_ALL:
3361 case XML_SCHEMA_TYPE_CHOICE:
3362 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3363 break;
3364 case XML_SCHEMA_TYPE_BASIC:
3365 case XML_SCHEMA_TYPE_ANY:
3366 case XML_SCHEMA_TYPE_FACET:
3367 case XML_SCHEMA_TYPE_SIMPLE:
3368 case XML_SCHEMA_TYPE_UR:
3369 case XML_SCHEMA_TYPE_ELEMENT:
3370 case XML_SCHEMA_TYPE_ATTRIBUTE:
3371 case XML_SCHEMA_TYPE_NOTATION:
3372 case XML_SCHEMA_TYPE_LIST:
3373 case XML_SCHEMA_TYPE_UNION:
3374 case XML_SCHEMA_FACET_MININCLUSIVE:
3375 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3376 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3377 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
3378 case XML_SCHEMA_FACET_TOTALDIGITS:
3379 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3380 case XML_SCHEMA_FACET_PATTERN:
3381 case XML_SCHEMA_FACET_ENUMERATION:
3382 case XML_SCHEMA_FACET_WHITESPACE:
3383 case XML_SCHEMA_FACET_LENGTH:
3384 case XML_SCHEMA_FACET_MAXLENGTH:
3385 case XML_SCHEMA_FACET_MINLENGTH:
3386 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
3387 break;
3388 }
3389 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003390#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003391 if (typeDecl->node != NULL) {
3392 xmlGenericError(xmlGenericErrorContext,
3393 "Type of %s : %s:%d :", name, typeDecl->node->doc->URL,
3394 xmlGetLineNo(typeDecl->node));
3395 } else {
3396 xmlGenericError(xmlGenericErrorContext,
3397 "Type of %s :", name);
3398 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003399 switch (typeDecl->contentType) {
3400 case XML_SCHEMA_CONTENT_SIMPLE:
3401 xmlGenericError(xmlGenericErrorContext,
3402 "simple\n"); break;
3403 case XML_SCHEMA_CONTENT_ELEMENTS:
3404 xmlGenericError(xmlGenericErrorContext,
3405 "elements\n"); break;
3406 case XML_SCHEMA_CONTENT_UNKNOWN:
3407 xmlGenericError(xmlGenericErrorContext,
3408 "unknown !!!\n"); break;
3409 case XML_SCHEMA_CONTENT_EMPTY:
3410 xmlGenericError(xmlGenericErrorContext,
3411 "empty\n"); break;
3412 case XML_SCHEMA_CONTENT_MIXED:
3413 xmlGenericError(xmlGenericErrorContext,
3414 "mixed\n"); break;
3415 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
3416 xmlGenericError(xmlGenericErrorContext,
3417 "mixed or elems\n"); break;
3418 case XML_SCHEMA_CONTENT_BASIC:
3419 xmlGenericError(xmlGenericErrorContext,
3420 "basic\n"); break;
3421 default:
3422 xmlGenericError(xmlGenericErrorContext,
3423 "not registered !!!\n"); break;
3424 }
3425#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003426}
3427
3428/**
3429 * xmlSchemaCheckDefaults:
3430 * @typeDecl: the schema type definition
3431 * @ctxt: the schema parser context
3432 *
3433 * Checks the default values types, especially for facets
3434 */
3435static void
3436xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
3437 xmlSchemaParserCtxtPtr ctxt,
3438 const xmlChar *name)
3439{
3440 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
3441 if (name == NULL)
3442 name = typeDecl->name;
3443 if (nonNegativeIntegerType == NULL) {
3444 nonNegativeIntegerType = xmlSchemaGetPredefinedType(
3445 BAD_CAST "nonNegativeInteger", xmlSchemaNs);
3446 }
3447 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
3448 if (typeDecl->facets != NULL) {
3449 xmlSchemaFacetPtr facet = typeDecl->facets;
3450 while (facet != NULL) {
3451 switch (facet->type) {
3452 case XML_SCHEMA_FACET_MININCLUSIVE:
3453 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3454 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3455 case XML_SCHEMA_FACET_MAXEXCLUSIVE: {
3456 /*
3457 * Okay we need to validate the value
3458 * at that point.
3459 */
3460 xmlSchemaValidCtxtPtr vctxt;
3461
3462 vctxt = xmlSchemaNewValidCtxt(NULL);
3463 if (vctxt == NULL)
3464 break;
3465 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3466 facet->value);
3467 facet->val = vctxt->value;
3468 vctxt->value = NULL;
3469 if (facet->val == NULL) {
3470 /* error code */
3471 xmlSchemaErrorContext(ctxt, NULL,
3472 facet->node, NULL);
3473 ctxt->error(ctxt->userData,
3474 "Schemas: type %s facet value %s invalid\n",
3475 name, facet->value);
3476 }
3477 xmlSchemaFreeValidCtxt(vctxt);
3478 break;
3479 }
3480 case XML_SCHEMA_FACET_ENUMERATION: {
3481 /*
3482 * Okay we need to validate the value
3483 * at that point.
3484 */
3485 xmlSchemaValidCtxtPtr vctxt;
3486 int ret;
3487
3488 vctxt = xmlSchemaNewValidCtxt(NULL);
3489 if (vctxt == NULL)
3490 break;
3491 ret = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3492 facet->value);
3493 if (ret != 0) {
3494 xmlSchemaErrorContext(ctxt, NULL,
3495 facet->node, NULL);
3496 ctxt->error(ctxt->userData,
3497 "Schemas: type %s enumeration value %s invalid\n",
3498 name, facet->value);
3499 }
3500 xmlSchemaFreeValidCtxt(vctxt);
3501 break;
3502 }
3503 case XML_SCHEMA_FACET_PATTERN:
3504 facet->regexp = xmlRegexpCompile(facet->value);
3505 if (facet->regexp == NULL) {
3506 /* error code */
3507 ctxt->error(ctxt->userData,
3508 "Schemas: type %s facet regexp %s invalid\n",
3509 name, facet->value);
3510 }
3511 break;
3512 case XML_SCHEMA_FACET_TOTALDIGITS:
3513 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3514 case XML_SCHEMA_FACET_LENGTH:
3515 case XML_SCHEMA_FACET_MAXLENGTH:
3516 case XML_SCHEMA_FACET_MINLENGTH: {
3517 int ret;
3518
3519 ret = xmlSchemaValidatePredefinedType(
3520 nonNegativeIntegerType, facet->value,
3521 &facet->val);
3522 if (ret != 0) {
3523 /* error code */
3524 xmlSchemaErrorContext(ctxt, NULL,
3525 facet->node, NULL);
3526 ctxt->error(ctxt->userData,
3527 "Schemas: type %s facet value %s invalid\n",
3528 name, facet->value);
3529 }
3530 break;
3531 }
3532 case XML_SCHEMA_FACET_WHITESPACE: {
3533 if (xmlStrEqual(facet->value, BAD_CAST"preserve")) {
3534 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
3535 } else if (xmlStrEqual(facet->value,
3536 BAD_CAST"replace")) {
3537 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
3538 } else if (xmlStrEqual(facet->value,
3539 BAD_CAST"collapse")) {
3540 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
3541 } else {
3542 xmlSchemaErrorContext(ctxt, NULL,
3543 facet->node, NULL);
3544 ctxt->error(ctxt->userData,
3545 "Schemas: type %s whiteSpace value %s invalid\n",
3546 name, facet->value);
3547 }
3548 }
3549 default:
3550 break;
3551 }
3552 facet = facet->next;
3553 }
3554 }
3555 }
3556}
3557
3558/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00003559 * xmlSchemaAttrGrpFixup:
3560 * @attrgrpDecl: the schema attribute definition
3561 * @ctxt: the schema parser context
3562 * @name: the attribute name
3563 *
3564 * Fixes finish doing the computations on the attributes definitions
3565 */
3566static void
3567xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
3568 xmlSchemaParserCtxtPtr ctxt,
3569 const xmlChar *name)
3570{
3571 if (name == NULL)
3572 name = attrgrpDecl->name;
3573 if (attrgrpDecl->attributes != NULL)
3574 return;
3575 if (attrgrpDecl->ref != NULL) {
3576 xmlSchemaAttributeGroupPtr ref;
3577
3578 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
3579 attrgrpDecl->refNs);
3580 if (ref == NULL) {
3581 if ((ctxt != NULL) && (ctxt->error != NULL))
3582 ctxt->error(ctxt->userData,
3583 "Schemas: attribute group %s reference %s not found\n",
3584 name, attrgrpDecl->ref);
3585 return;
3586 }
3587 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
3588 attrgrpDecl->attributes = ref->attributes;
3589 } else {
3590 if ((ctxt != NULL) && (ctxt->error != NULL))
3591 ctxt->error(ctxt->userData,
3592 "Schemas: attribute %s has no attributes nor reference\n",
3593 name);
3594 }
3595}
3596
3597/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003598 * xmlSchemaAttrFixup:
3599 * @attrDecl: the schema attribute definition
3600 * @ctxt: the schema parser context
3601 * @name: the attribute name
3602 *
3603 * Fixes finish doing the computations on the attributes definitions
3604 */
3605static void
3606xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
3607 xmlSchemaParserCtxtPtr ctxt,
3608 const xmlChar *name)
3609{
3610 if (name == NULL)
3611 name = attrDecl->name;
3612 if (attrDecl->subtypes != NULL)
3613 return;
3614 if (attrDecl->typeName != NULL) {
3615 xmlSchemaTypePtr type;
3616
3617 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
3618 attrDecl->typeNs);
3619 if (type == NULL) {
3620 if ((ctxt != NULL) && (ctxt->error != NULL))
3621 ctxt->error(ctxt->userData,
3622 "Schemas: attribute %s type %s not found\n",
3623 name, attrDecl->typeName);
3624 }
3625 attrDecl->subtypes = type;
3626 } else if (attrDecl->ref != NULL) {
3627 xmlSchemaAttributePtr ref;
3628
3629 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
3630 attrDecl->refNs);
3631 if (ref == NULL) {
3632 if ((ctxt != NULL) && (ctxt->error != NULL))
3633 ctxt->error(ctxt->userData,
3634 "Schemas: attribute %s reference %s not found\n",
3635 name, attrDecl->ref);
3636 return;
3637 }
3638 xmlSchemaAttrFixup(ref, ctxt, NULL);
3639 attrDecl->subtypes = ref->subtypes;
3640 } else {
3641 if ((ctxt != NULL) && (ctxt->error != NULL))
3642 ctxt->error(ctxt->userData,
3643 "Schemas: attribute %s has no type nor reference\n",
3644 name);
3645 }
3646}
3647
3648/**
3649 * xmlSchemaParse:
3650 * @ctxt: a schema validation context
3651 * @URL: the location of the schema
3652 *
3653 * Load, XML parse a schema definition resource and build an internal
3654 * XML Shema struture which can be used to validate instances.
3655 * *WARNING* this interface is highly subject to change
3656 *
3657 * Returns the internal XML Schema structure built from the resource or
3658 * NULL in case of error
3659 */
3660xmlSchemaPtr
3661xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
3662{
3663 xmlSchemaPtr ret = NULL;
3664 xmlDocPtr doc;
3665 xmlNodePtr root, cur, delete;
3666
3667 xmlSchemaInitTypes();
3668
3669 if ((ctxt == NULL) || (ctxt->URL == NULL))
3670 return (NULL);
3671
3672 ctxt->counter = 0;
3673 ctxt->container = NULL;
3674
3675 /*
3676 * First step is to parse the input document into an DOM/Infoset
3677 */
3678 doc = xmlParseFile((const char *) ctxt->URL);
3679 if (doc == NULL) {
3680 if (ctxt->error != NULL)
3681 ctxt->error(ctxt->userData,
3682 "xmlSchemaParse: could not load %s\n", ctxt->URL);
3683 return (NULL);
3684 }
3685
3686 /*
3687 * Then extract the root and Schema parse it
3688 */
3689 root = xmlDocGetRootElement(doc);
3690 if (root == NULL) {
3691 if (ctxt->error != NULL)
3692 ctxt->error(ctxt->userData, "xmlSchemaParse: %s is empty\n",
3693 ctxt->URL);
3694 return (NULL);
3695 }
3696
3697 /*
3698 * Remove all the blank text nodes
3699 */
3700 delete = NULL;
3701 cur = root;
3702 while (cur != NULL) {
3703 if (delete != NULL) {
3704 xmlUnlinkNode(delete);
3705 xmlFreeNode(delete);
3706 delete = NULL;
3707 }
3708 if (cur->type == XML_TEXT_NODE) {
3709 if (IS_BLANK_NODE(cur)) {
3710 if (xmlNodeGetSpacePreserve(cur) != 1) {
3711 delete = cur;
3712 }
3713 }
3714 } else if ((cur->type != XML_ELEMENT_NODE) &&
3715 (cur->type != XML_CDATA_SECTION_NODE)) {
3716 delete = cur;
3717 goto skip_children;
3718 }
3719
3720 /*
3721 * Skip to next node
3722 */
3723 if (cur->children != NULL) {
3724 if ((cur->children->type != XML_ENTITY_DECL) &&
3725 (cur->children->type != XML_ENTITY_REF_NODE) &&
3726 (cur->children->type != XML_ENTITY_NODE)) {
3727 cur = cur->children;
3728 continue;
3729 }
3730 }
3731skip_children:
3732 if (cur->next != NULL) {
3733 cur = cur->next;
3734 continue;
3735 }
3736
3737 do {
3738 cur = cur->parent;
3739 if (cur == NULL)
3740 break;
3741 if (cur == root) {
3742 cur = NULL;
3743 break;
3744 }
3745 if (cur->next != NULL) {
3746 cur = cur->next;
3747 break;
3748 }
3749 } while (cur != NULL);
3750 }
3751 if (delete != NULL) {
3752 xmlUnlinkNode(delete);
3753 xmlFreeNode(delete);
3754 delete = NULL;
3755 }
3756
3757 /*
3758 * Then do the parsing for good
3759 */
3760 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillardb4398962002-04-19 07:01:55 +00003761 if (ret == NULL)
3762 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003763 ret->doc = doc;
3764
3765 /*
3766 * Then fix all the references.
3767 */
3768 ctxt->schema = ret;
3769 xmlHashScanFull(ret->elemDecl,
3770 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
3771
3772 /*
3773 * Then fixup all types properties
3774 */
3775 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
3776
3777 /*
3778 * Then build the content model for all elements
3779 */
3780 xmlHashScan(ret->elemDecl,
3781 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
3782
3783 /*
3784 * Then check the defaults part of the type like facets values
3785 */
3786 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt);
3787
3788 /*
3789 * Then fixup all attributes declarations
3790 */
3791 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
3792
Daniel Veillard13e04c62002-04-23 17:51:29 +00003793 /*
3794 * Then fixup all attributes group declarations
3795 */
3796 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup, ctxt);
3797
Daniel Veillard4255d502002-04-16 15:50:10 +00003798 return (ret);
3799}
3800
3801/**
3802 * xmlSchemaParse:
3803 * @ctxt: a schema validation context
3804 * @URL: the location of the schema
3805 *
3806 * Load, XML parse a schema definition resource and build an internal
3807 * XML Shema struture which can be used to validate instances.
3808 * *WARNING* this interface is highly subject to change
3809 *
3810 * Returns the internal XML Schema structure built from the resource or
3811 * NULL in case of error
3812 */
3813void
3814xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
3815 xmlSchemaValidityErrorFunc err,
3816 xmlSchemaValidityWarningFunc warn, void *ctx) {
3817 if (ctxt == NULL)
3818 return;
3819 ctxt->error = err;
3820 ctxt->warning = warn;
3821 ctxt->userData = ctx;
3822}
3823
3824/************************************************************************
3825 * *
3826 * Simple type validation *
3827 * *
3828 ************************************************************************/
3829
3830/**
3831 * xmlSchemaValidateSimpleValue:
3832 * @ctxt: a schema validation context
3833 * @type: the type declaration
3834 * @value: the value to validate
3835 *
3836 * Validate a value against a simple type
3837 *
3838 * Returns 0 if the value is valid, a positive error code
3839 * number otherwise and -1 in case of internal or API error.
3840 */
3841static int
3842xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
3843 xmlSchemaTypePtr type,
3844 xmlChar *value) {
3845 int ret = 0;
3846 /*
3847 * First normalize the value accordingly to Schema Datatype
3848 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
3849 */
3850 /*
3851 * Then check the normalized value against the lexical space of the
3852 * type.
3853 */
3854 if (type->type == XML_SCHEMA_TYPE_BASIC) {
3855 if (ctxt->value != NULL) {
3856 xmlSchemaFreeValue(ctxt->value);
3857 ctxt->value = NULL;
3858 }
3859 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
3860 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
3861 xmlSchemaTypePtr base;
3862 xmlSchemaFacetPtr facet;
3863 int tmp;
3864
3865 base = type->baseType;
3866 if (base != NULL) {
3867 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
3868 } else if (type->subtypes != NULL) {
3869
3870 }
3871 /*
3872 * Do not validate facets when working on building the Schemas
3873 */
3874 if (ctxt->schema != NULL) {
3875 if (ret == 0) {
3876 facet = type->facets;
Daniel Veillard88c58912002-04-23 07:12:20 +00003877 if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) &&
3878 (facet != NULL) &&
3879 (facet->type == XML_SCHEMA_FACET_ENUMERATION)) {
3880 while (facet != NULL) {
3881 ret = 1;
3882
3883 tmp = xmlSchemaValidateFacet(base, facet, value,
3884 ctxt->value);
3885 if (tmp == 0) {
3886 ret = 0;
3887 break;
3888 }
3889 facet = facet->next;
3890 }
3891 } else {
3892 while (facet != NULL) {
3893 tmp = xmlSchemaValidateFacet(base, facet, value,
3894 ctxt->value);
3895 if (tmp != 0)
3896 ret = tmp;
3897 facet = facet->next;
3898 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003899 }
3900 }
3901 }
3902 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
3903 xmlSchemaTypePtr base;
3904
3905 base = type->subtypes;
3906 if (base != NULL) {
3907 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
3908 } else {
3909 TODO
3910 }
3911 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
3912 xmlSchemaTypePtr base;
3913 xmlChar *cur, *end, tmp;
3914 int ret2;
3915
3916 base = type->subtypes;
3917 if (base == NULL) {
3918 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
3919 if (ctxt->error != NULL) {
3920 xmlSchemaErrorContext(NULL, ctxt->schema, type->node, NULL);
3921 ctxt->error(ctxt->userData,
3922 "Internal: List type %s has no base type\n",
3923 type->name);
3924 }
3925 return(-1);
3926 }
3927 cur = value;
3928 do {
3929 while (IS_BLANK(*cur)) cur++;
3930 end = cur;
3931 while ((*end != 0) && (!(IS_BLANK(*end)))) end++;
3932 if (end == cur)
3933 break;
3934 tmp = *end;
3935 *end = 0;
3936 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, cur);
3937 if (ret2 != 0)
3938 ret = 1;
3939 *end = tmp;
3940 cur = end;
3941 } while (*cur != 0);
3942 } else {
3943 TODO
3944 }
3945 return(ret);
3946}
3947
3948/************************************************************************
3949 * *
3950 * DOM Validation code *
3951 * *
3952 ************************************************************************/
3953
3954static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
3955 xmlNodePtr node);
3956static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
3957 xmlNodePtr elem, xmlSchemaAttributePtr attributes);
3958static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
3959 xmlNodePtr elem, xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type);
3960
3961/**
3962 * xmlSchemaRegisterAttributes:
3963 * @ctxt: a schema validation context
3964 * @attrs: a list of attributes
3965 *
3966 * Register the list of attributes as the set to be validated on that element
3967 *
3968 * Returns -1 in case of error, 0 otherwise
3969 */
3970static int
3971xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt,
3972 xmlAttrPtr attrs) {
3973 while (attrs != NULL) {
Daniel Veillard441bc322002-04-20 17:38:48 +00003974 if ((attrs->ns != NULL) &&
3975 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
3976 attrs = attrs->next;
3977 continue;
3978 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003979 if (ctxt->attrNr >= ctxt->attrMax) {
3980 xmlSchemaAttrStatePtr tmp;
3981
3982 ctxt->attrMax *= 2;
3983 tmp = (xmlSchemaAttrStatePtr)
3984 xmlRealloc(ctxt->attr, ctxt->attrMax *
3985 sizeof(xmlSchemaAttrState));
3986 if (tmp == NULL) {
3987 ctxt->attrMax /= 2;
3988 return(-1);
3989 }
3990 ctxt->attr = tmp;
3991 }
3992 ctxt->attr[ctxt->attrNr].attr = attrs;
3993 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
3994 ctxt->attrNr++;
3995 attrs = attrs->next;
3996 }
3997 return(0);
3998}
3999
4000/**
4001 * xmlSchemaCheckAttributes:
4002 * @ctxt: a schema validation context
4003 * @node: the node carrying it.
4004 *
4005 * Check that the registered set of attributes on the current node
4006 * has been properly validated.
4007 *
4008 * Returns 0 if validity constraints are met, 1 otherwise.
4009 */
4010static int
4011xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4012 int ret = 0;
4013 int i;
4014
4015 for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
4016 if (ctxt->attr[i].attr == NULL)
4017 break;
4018 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
4019 ret = 1;
4020 ctxt->err = XML_SCHEMAS_ERR_ATTRUNKNOWN;
4021 if (ctxt->error != NULL)
4022 ctxt->error(ctxt->userData,
4023 "Attribute %s on %s is unknown\n",
4024 ctxt->attr[i].attr->name,
4025 node->name);
4026 }
4027 }
4028 return(ret);
4029}
4030
4031/**
4032 * xmlSchemaValidateSimpleContent:
4033 * @ctxt: a schema validation context
4034 * @elem: an element
4035 * @type: the type declaration
4036 *
4037 * Validate the content of an element expected to be a simple type
4038 *
4039 * Returns 0 if the element is schemas valid, a positive error code
4040 * number otherwise and -1 in case of internal or API error.
4041 */
4042static int
4043xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
4044 ATTRIBUTE_UNUSED xmlNodePtr node) {
4045 xmlNodePtr child;
4046 xmlSchemaTypePtr type, base;
4047 xmlChar *value;
4048 int ret = 0, tmp;
4049
4050 child = ctxt->node;
4051 type = ctxt->type;
4052
4053 /*
4054 * Validation Rule: Element Locally Valid (Type): 3.1.3
4055 */
4056 value = xmlNodeGetContent(child);
4057 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
4058 switch (type->type) {
4059 case XML_SCHEMA_TYPE_RESTRICTION: {
4060 xmlSchemaFacetPtr facet;
4061
4062 base = type->baseType;
4063 if (base != NULL) {
4064 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4065 } else {
4066 TODO
4067 }
4068 if (ret == 0) {
4069 facet = type->facets;
4070 while (facet != NULL) {
4071 tmp = xmlSchemaValidateFacet(base, facet, value,
4072 ctxt->value);
4073 if (tmp != 0)
4074 ret = tmp;
4075 facet = facet->next;
4076 }
4077 }
4078 break;
4079 }
4080 default:
4081 TODO
4082 }
4083 if (value != NULL)
4084 xmlFree(value);
4085
4086 return(ret);
4087}
4088
4089/**
4090 * xmlSchemaValidateCheckNodeList
4091 * @nodelist: the list of nodes
4092 *
4093 * Check the node list is only made of text nodes and entities pointing
4094 * to text nodes
4095 *
4096 * Returns 1 if true, 0 if false and -1 in case of error
4097 */
4098static int
4099xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist) {
4100 while (nodelist != NULL) {
4101 if (nodelist->type == XML_ENTITY_REF_NODE) {
4102 TODO /* implement recursion in the entity content */
4103 }
4104 if ((nodelist->type != XML_TEXT_NODE) &&
4105 (nodelist->type != XML_COMMENT_NODE) &&
4106 (nodelist->type != XML_PI_NODE) &&
4107 (nodelist->type != XML_PI_NODE)) {
4108 return(0);
4109 }
4110 nodelist = nodelist->next;
4111 }
4112 return(1);
4113}
4114
4115/**
4116 * xmlSchemaSkipIgnored:
4117 * @ctxt: a schema validation context
4118 * @type: the current type context
4119 * @node: the top node.
4120 *
4121 * Skip ignorable nodes in that context
4122 *
4123 * Returns the new sibling
4124 * number otherwise and -1 in case of internal or API error.
4125 */
4126static xmlNodePtr
4127xmlSchemaSkipIgnored(ATTRIBUTE_UNUSED xmlSchemaValidCtxtPtr ctxt,
4128 xmlSchemaTypePtr type,
4129 xmlNodePtr node) {
4130 int mixed = 0;
4131 /*
4132 * TODO complete and handle entities
4133 */
4134 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
4135 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
4136 while ((node != NULL) &&
4137 ((node->type == XML_COMMENT_NODE) ||
4138 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
4139 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
4140 (node->type == XML_TEXT_NODE) &&
4141 (IS_BLANK_NODE(node)))))) {
4142 node = node->next;
4143 }
4144 return(node);
4145}
4146
4147/**
4148 * xmlSchemaValidateCallback:
4149 * @ctxt: a schema validation context
4150 * @name: the name of the element detected (might be NULL)
4151 * @type: the type
4152 *
4153 * A transition has been made in the automata associated to an element
4154 * content model
4155 */
4156static void
4157xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
4158 ATTRIBUTE_UNUSED const xmlChar *name,
4159 xmlSchemaTypePtr type,
4160 xmlNodePtr node) {
4161 xmlSchemaTypePtr oldtype = ctxt->type;
4162 xmlNodePtr oldnode = ctxt->node;
4163#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00004164 xmlGenericError(xmlGenericErrorContext,
4165 "xmlSchemaValidateCallback: %s, %s, %s\n",
4166 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004167#endif
4168 ctxt->type = type;
4169 ctxt->node = node;
4170 xmlSchemaValidateContent(ctxt, node);
4171 ctxt->type = oldtype;
4172 ctxt->node = oldnode;
4173}
4174
4175
4176#if 0
4177/**
4178 * xmlSchemaValidateSimpleRestrictionType:
4179 * @ctxt: a schema validation context
4180 * @node: the top node.
4181 *
4182 * Validate the content of a restriction type.
4183 *
4184 * Returns 0 if the element is schemas valid, a positive error code
4185 * number otherwise and -1 in case of internal or API error.
4186 */
4187static int
4188xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
4189 xmlNodePtr node)
4190{
4191 xmlNodePtr child;
4192 xmlSchemaTypePtr type;
4193 int ret;
4194
4195 child = ctxt->node;
4196 type = ctxt->type;
4197
4198 if ((ctxt == NULL) || (type == NULL)) {
4199 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4200 if (ctxt->error != NULL)
4201 ctxt->error(ctxt->userData,
4202 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
4203 node->name);
4204 return (-1);
4205 }
4206 /*
4207 * Only text and text based entities references shall be found there
4208 */
4209 ret = xmlSchemaValidateCheckNodeList(child);
4210 if (ret < 0) {
4211 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4212 if (ctxt->error != NULL)
4213 ctxt->error(ctxt->userData,
4214 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4215 node->name);
4216 return (-1);
4217 } else if (ret == 0) {
4218 ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4219 if (ctxt->error != NULL)
4220 ctxt->error(ctxt->userData,
4221 "Element %s content is not a simple type\n",
4222 node->name);
4223 return (-1);
4224 }
4225 ctxt->type = type->subtypes;
4226 xmlSchemaValidateContent(ctxt, node);
4227 ctxt->type = type;
4228 return (ret);
4229}
4230#endif
4231
4232/**
4233 * xmlSchemaValidateSimpleType:
4234 * @ctxt: a schema validation context
4235 * @node: the top node.
4236 *
4237 * Validate the content of an simple type.
4238 *
4239 * Returns 0 if the element is schemas valid, a positive error code
4240 * number otherwise and -1 in case of internal or API error.
4241 */
4242static int
4243xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4244 xmlNodePtr child;
4245 xmlSchemaTypePtr type;
4246 xmlAttrPtr attr;
4247 int ret;
4248
4249 child = ctxt->node;
4250 type = ctxt->type;
4251
4252 if ((ctxt == NULL) || (type == NULL)) {
4253 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4254 if (ctxt->error != NULL)
4255 ctxt->error(ctxt->userData,
4256 "Internal error: xmlSchemaValidateSimpleType %s\n",
4257 node->name);
4258 return(-1);
4259 }
4260 /*
4261 * Only text and text based entities references shall be found there
4262 */
4263 ret = xmlSchemaValidateCheckNodeList(child);
4264 if (ret < 0) {
4265 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4266 if (ctxt->error != NULL)
4267 ctxt->error(ctxt->userData,
4268 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4269 node->name);
4270 return(-1);
4271 } else if (ret == 0) {
4272 ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4273 if (ctxt->error != NULL)
4274 ctxt->error(ctxt->userData,
4275 "Element %s content is not a simple type\n",
4276 node->name);
4277 return(-1);
4278 }
4279 /*
4280 * Validation Rule: Element Locally Valid (Type): 3.1.1
4281 */
4282 attr = node->properties;
4283 while (attr != NULL) {
4284 if ((attr->ns == NULL) ||
4285 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
4286 ((!xmlStrEqual(attr->name, BAD_CAST"type")) &&
4287 (!xmlStrEqual(attr->name, BAD_CAST"nil")) &&
4288 (!xmlStrEqual(attr->name, BAD_CAST"schemasLocation")) &&
4289 (!xmlStrEqual(attr->name, BAD_CAST"noNamespaceSchemaLocation")))) {
4290 ctxt->err = XML_SCHEMAS_ERR_INVALIDATTR;
4291 if (ctxt->error != NULL)
4292 ctxt->error(ctxt->userData,
4293 "Element %s: attribute %s should not be present\n",
4294 child->name, attr->name);
4295 return(ctxt->err);
4296 }
4297 }
4298
4299 ctxt->type = type->subtypes;
4300 ret = xmlSchemaValidateSimpleContent(ctxt, node);
4301 ctxt->type = type;
4302 return(ret);
4303}
4304
4305/**
4306 * xmlSchemaValidateElementType:
4307 * @ctxt: a schema validation context
4308 * @node: the top node.
4309 *
4310 * Validate the content of an element type.
4311 * Validation Rule: Element Locally Valid (Complex Type)
4312 *
4313 * Returns 0 if the element is schemas valid, a positive error code
4314 * number otherwise and -1 in case of internal or API error.
4315 */
4316static int
4317xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4318 xmlNodePtr child;
4319 xmlSchemaTypePtr type;
4320 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
4321 xmlSchemaElementPtr decl;
4322 int ret, attrBase;
4323
4324 oldregexp = ctxt->regexp;
4325
4326 child = ctxt->node;
4327 type = ctxt->type;
4328
4329 if ((ctxt == NULL) || (type == NULL)) {
4330 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4331 if (ctxt->error != NULL)
4332 ctxt->error(ctxt->userData,
4333 "Internal error: xmlSchemaValidateElementType\n",
4334 node->name);
4335 return(-1);
4336 }
4337 if (child == NULL) {
4338 if (type->minOccurs > 0) {
4339 ctxt->err = XML_SCHEMAS_ERR_MISSING;
4340 if (ctxt->error != NULL)
4341 ctxt->error(ctxt->userData,
4342 "Element %s: missing child %s\n",
4343 node->name, type->name);
4344 }
4345 return(ctxt->err);
4346 }
4347
4348 /*
4349 * Verify the element matches
4350 */
4351 if (!xmlStrEqual(child->name, type->name)) {
4352 ctxt->err = XML_SCHEMAS_ERR_WRONGELEM;
4353 if (ctxt->error != NULL)
4354 ctxt->error(ctxt->userData,
4355 "Element %s: missing child %s found %s\n",
4356 node->name, type->name, child->name);
4357 return(ctxt->err);
4358 }
4359 /*
4360 * Verify the attributes
4361 */
4362 attrBase = ctxt->attrBase;
4363 ctxt->attrBase = ctxt->attrNr;
4364 xmlSchemaRegisterAttributes(ctxt, child->properties);
4365 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
4366 /*
4367 * Verify the element content recursively
4368 */
4369 decl = (xmlSchemaElementPtr) type;
4370 oldregexp = ctxt->regexp;
4371 if (decl->contModel != NULL) {
4372 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
4373 (xmlRegExecCallbacks) xmlSchemaValidateCallback,
4374 ctxt);
4375#ifdef DEBUG_AUTOMATA
4376 xmlGenericError(xmlGenericErrorContext,
4377 "====> %s\n", node->name);
4378#endif
4379 }
4380 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr)type,
4381 type->subtypes);
4382
4383 if (decl->contModel != NULL) {
4384 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
4385#ifdef DEBUG_AUTOMATA
4386 xmlGenericError(xmlGenericErrorContext,
4387 "====> %s : %d\n", node->name, ret);
4388#endif
4389 if (ret == 0) {
Daniel Veillard8651f532002-04-17 09:06:27 +00004390 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
Daniel Veillard4255d502002-04-16 15:50:10 +00004391 if (ctxt->error != NULL)
4392 ctxt->error(ctxt->userData, "Element %s content check failed\n",
4393 node->name);
4394 } else if (ret < 0) {
Daniel Veillard8651f532002-04-17 09:06:27 +00004395 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
Daniel Veillard4255d502002-04-16 15:50:10 +00004396 if (ctxt->error != NULL)
4397 ctxt->error(ctxt->userData, "Element %s content check failure\n",
4398 node->name);
4399#ifdef DEBUG_CONTENT
4400 } else {
4401 xmlGenericError(xmlGenericErrorContext,
4402 "Element %s content check succeeded\n", node->name);
4403
4404#endif
4405 }
4406 xmlRegFreeExecCtxt(ctxt->regexp);
4407 }
4408 /*
4409 * Verify that all attributes were Schemas-validated
4410 */
4411 xmlSchemaCheckAttributes(ctxt, node);
4412 ctxt->attrNr = ctxt->attrBase;
4413 ctxt->attrBase = attrBase;
4414
4415 ctxt->regexp = oldregexp;
4416
4417 ctxt->node = child;
4418 ctxt->type = type;
4419 return(ctxt->err);
4420}
4421
4422/**
4423 * xmlSchemaValidateBasicType:
4424 * @ctxt: a schema validation context
4425 * @node: the top node.
4426 *
4427 * Validate the content of an element expected to be a basic type type
4428 *
4429 * Returns 0 if the element is schemas valid, a positive error code
4430 * number otherwise and -1 in case of internal or API error.
4431 */
4432static int
4433xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4434 int ret;
4435 xmlNodePtr child, cur;
4436 xmlSchemaTypePtr type;
4437 xmlChar *value; /* lexical representation */
4438
4439 child = ctxt->node;
4440 type = ctxt->type;
4441
4442 if ((ctxt == NULL) || (type == NULL)) {
4443 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4444 if (ctxt->error != NULL)
4445 ctxt->error(ctxt->userData,
4446 "Internal error: xmlSchemaValidateBasicType\n",
4447 node->name);
4448 return(-1);
4449 }
4450 /*
4451 * First check the content model of the node.
4452 */
4453 cur = child;
4454 while (cur != NULL) {
4455 switch (cur->type) {
4456 case XML_TEXT_NODE:
4457 case XML_CDATA_SECTION_NODE:
4458 case XML_PI_NODE:
4459 case XML_COMMENT_NODE:
4460 case XML_XINCLUDE_START:
4461 case XML_XINCLUDE_END:
4462 break;
4463 case XML_ENTITY_REF_NODE:
4464 case XML_ENTITY_NODE:
4465 TODO
4466 break;
4467 case XML_ELEMENT_NODE:
4468 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
4469 if (ctxt->error != NULL)
4470 ctxt->error(ctxt->userData,
4471 "Element %s: child %s should not be present\n",
4472 node->name, cur->name);
4473 return(ctxt->err);
4474 case XML_ATTRIBUTE_NODE:
4475 case XML_DOCUMENT_NODE:
4476 case XML_DOCUMENT_TYPE_NODE:
4477 case XML_DOCUMENT_FRAG_NODE:
4478 case XML_NOTATION_NODE:
4479 case XML_HTML_DOCUMENT_NODE:
4480 case XML_DTD_NODE:
4481 case XML_ELEMENT_DECL:
4482 case XML_ATTRIBUTE_DECL:
4483 case XML_ENTITY_DECL:
4484 case XML_NAMESPACE_DECL:
4485#ifdef LIBXML_DOCB_ENABLED
4486 case XML_DOCB_DOCUMENT_NODE:
4487#endif
4488 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
4489 if (ctxt->error != NULL)
4490 ctxt->error(ctxt->userData,
4491 "Element %s: node type %d unexpected here\n",
4492 node->name, cur->type);
4493 return(ctxt->err);
4494 }
4495 cur = cur->next;
4496 }
4497 if (child == NULL)
4498 value = NULL;
4499 else
4500 value = xmlNodeGetContent(child->parent);
4501
4502 if (ctxt->value != NULL) {
4503 xmlSchemaFreeValue(ctxt->value);
4504 ctxt->value = NULL;
4505 }
4506 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
4507 if (value != NULL)
4508 xmlFree(value);
4509 if (ret != 0) {
4510 ctxt->error(ctxt->userData,
4511 "Element %s: failed to validate basic type %s\n",
4512 node->name, type->name);
4513 }
4514 return(ret);
4515}
4516
4517/**
4518 * xmlSchemaValidateComplexType:
4519 * @ctxt: a schema validation context
4520 * @node: the top node.
4521 *
4522 * Validate the content of an element expected to be a complex type type
4523 * xmlschema-1.html#cvc-complex-type
4524 * Validation Rule: Element Locally Valid (Complex Type)
4525 *
4526 * Returns 0 if the element is schemas valid, a positive error code
4527 * number otherwise and -1 in case of internal or API error.
4528 */
4529static int
4530xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4531 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00004532 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004533 int ret;
4534
4535 child = ctxt->node;
4536 type = ctxt->type;
4537
Daniel Veillard4255d502002-04-16 15:50:10 +00004538 switch (type->contentType) {
4539 case XML_SCHEMA_CONTENT_EMPTY:
4540 if (child != NULL) {
4541 if (ctxt->error != NULL)
4542 ctxt->error(ctxt->userData,
4543 "Element %s is supposed to be empty\n",
4544 node->name);
4545 }
Daniel Veillarde19fc232002-04-22 16:01:24 +00004546 if (type->attributes != NULL) {
4547 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4548 }
4549 subtype = type->subtypes;
4550 while (subtype != NULL) {
4551 ctxt->type = subtype;
4552 xmlSchemaValidateComplexType(ctxt, node);
4553 subtype = subtype->next;
4554 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004555 break;
4556 case XML_SCHEMA_CONTENT_ELEMENTS:
4557 case XML_SCHEMA_CONTENT_MIXED:
4558 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4559 /*
4560 * Skip ignorable nodes in that context
4561 */
4562 child = xmlSchemaSkipIgnored(ctxt, type, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004563 while (child != NULL) {
4564 if (child->type == XML_ELEMENT_NODE) {
4565 ret = xmlRegExecPushString(ctxt->regexp,
4566 child->name, child);
4567#ifdef DEBUG_AUTOMATA
4568 if (ret < 0)
4569 xmlGenericError(xmlGenericErrorContext,
4570 " --> %s Error\n", child->name);
4571 else
4572 xmlGenericError(xmlGenericErrorContext,
4573 " --> %s\n", child->name);
4574#endif
4575 }
4576 child = child->next;
4577 /*
4578 * Skip ignorable nodes in that context
4579 */
4580 child = xmlSchemaSkipIgnored(ctxt, type, child);
4581 }
4582 break;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004583 case XML_SCHEMA_CONTENT_BASIC: {
4584 if (type->subtypes != NULL) {
4585 ctxt->type = type->subtypes;
4586 xmlSchemaValidateComplexType(ctxt, node);
4587 }
4588 if (type->baseType != NULL) {
4589 ctxt->type = type->baseType;
4590 xmlSchemaValidateBasicType(ctxt, node);
4591 }
4592 if (type->attributes != NULL) {
4593 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4594 }
4595 ctxt->type = type;
4596 break;
4597 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004598 default:
4599 TODO
4600 xmlGenericError(xmlGenericErrorContext,
4601 "unimplemented content type %d\n",
4602 type->contentType);
4603 }
4604 return(ctxt->err);
4605}
4606
4607/**
4608 * xmlSchemaValidateContent:
4609 * @ctxt: a schema validation context
4610 * @elem: an element
4611 * @type: the type declaration
4612 *
4613 * Validate the content of an element against the type.
4614 *
4615 * Returns 0 if the element is schemas valid, a positive error code
4616 * number otherwise and -1 in case of internal or API error.
4617 */
4618static int
4619xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4620 xmlNodePtr child;
4621 xmlSchemaTypePtr type;
4622
4623 child = ctxt->node;
4624 type = ctxt->type;
4625
Daniel Veillarde19fc232002-04-22 16:01:24 +00004626 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4627
Daniel Veillard4255d502002-04-16 15:50:10 +00004628 switch (type->type) {
4629 case XML_SCHEMA_TYPE_ANY:
4630 /* Any type will do it, fine */
4631 TODO /* handle recursivity */
4632 break;
4633 case XML_SCHEMA_TYPE_COMPLEX:
4634 xmlSchemaValidateComplexType(ctxt, node);
4635 break;
4636 case XML_SCHEMA_TYPE_ELEMENT: {
4637 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
4638 /*
4639 * Handle element reference here
4640 */
4641 if (decl->ref != NULL) {
4642 if (decl->refDecl == NULL) {
4643 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4644 if (ctxt->error != NULL)
4645 ctxt->error(ctxt->userData,
4646 "Internal error: element reference %s not resolved\n",
4647 decl->ref);
4648 return(-1);
4649 }
4650 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
4651 decl = decl->refDecl;
4652 }
4653 xmlSchemaValidateElementType(ctxt, node);
4654 ctxt->type = type;
4655 break;
4656 }
4657 case XML_SCHEMA_TYPE_BASIC:
4658 xmlSchemaValidateBasicType(ctxt, node);
4659 break;
4660 case XML_SCHEMA_TYPE_FACET:
4661 TODO
4662 break;
4663 case XML_SCHEMA_TYPE_SIMPLE:
4664 xmlSchemaValidateSimpleType(ctxt, node);
4665 break;
4666 case XML_SCHEMA_TYPE_SEQUENCE:
4667 TODO
4668 break;
4669 case XML_SCHEMA_TYPE_CHOICE:
4670 TODO
4671 break;
4672 case XML_SCHEMA_TYPE_ALL:
4673 TODO
4674 break;
4675 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
4676 TODO
4677 break;
4678 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4679 TODO
4680 break;
4681 case XML_SCHEMA_TYPE_UR:
4682 TODO
4683 break;
4684 case XML_SCHEMA_TYPE_RESTRICTION:
4685 /*xmlSchemaValidateRestrictionType(ctxt, node); */
4686 TODO
4687 break;
4688 case XML_SCHEMA_TYPE_EXTENSION:
4689 TODO
4690 break;
4691 case XML_SCHEMA_TYPE_ATTRIBUTE:
4692 TODO
4693 break;
4694 case XML_SCHEMA_TYPE_GROUP:
4695 TODO
4696 break;
4697 case XML_SCHEMA_TYPE_NOTATION:
4698 TODO
4699 break;
4700 case XML_SCHEMA_TYPE_LIST:
4701 TODO
4702 break;
4703 case XML_SCHEMA_TYPE_UNION:
4704 TODO
4705 break;
4706 case XML_SCHEMA_FACET_MININCLUSIVE:
4707 TODO
4708 break;
4709 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4710 TODO
4711 break;
4712 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4713 TODO
4714 break;
4715 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4716 TODO
4717 break;
4718 case XML_SCHEMA_FACET_TOTALDIGITS:
4719 TODO
4720 break;
4721 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4722 TODO
4723 break;
4724 case XML_SCHEMA_FACET_PATTERN:
4725 TODO
4726 break;
4727 case XML_SCHEMA_FACET_ENUMERATION:
4728 TODO
4729 break;
4730 case XML_SCHEMA_FACET_WHITESPACE:
4731 TODO
4732 break;
4733 case XML_SCHEMA_FACET_LENGTH:
4734 TODO
4735 break;
4736 case XML_SCHEMA_FACET_MAXLENGTH:
4737 TODO
4738 break;
4739 case XML_SCHEMA_FACET_MINLENGTH:
4740 TODO
4741 break;
4742 }
4743 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4744
4745 if (ctxt->node == NULL)
4746 return(ctxt->err);
4747 ctxt->node = ctxt->node->next;
4748 ctxt->type = type->next;
4749 return(ctxt->err);
4750}
4751
4752/**
4753 * xmlSchemaValidateType:
4754 * @ctxt: a schema validation context
4755 * @elem: an element
4756 * @type: the list of type declarations
4757 *
4758 * Validate the content of an element against the types.
4759 *
4760 * Returns 0 if the element is schemas valid, a positive error code
4761 * number otherwise and -1 in case of internal or API error.
4762 */
4763static int
4764xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
4765 xmlSchemaElementPtr elemDecl,
4766 xmlSchemaTypePtr type) {
4767 xmlChar *nil;
4768
4769 if ((elem->content == NULL) || (type == NULL) || (elemDecl == NULL))
4770 return(0);
4771 /*
4772 * 3.3.4 : 2
4773 */
4774 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
4775 ctxt->err = XML_SCHEMAS_ERR_ISABSTRACT;
4776 if (ctxt->error != NULL)
4777 ctxt->error(ctxt->userData, "Element %s is abstract\n", elem->name);
4778 return(ctxt->err);
4779 }
4780 /*
4781 * 3.3.4: 3
4782 */
4783 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
4784 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
4785 /* 3.3.4: 3.2 */
4786 if (xmlStrEqual(nil, BAD_CAST "true")) {
4787 if (elem->children != NULL) {
4788 ctxt->err = XML_SCHEMAS_ERR_NOTEMPTY;
4789 if (ctxt->error != NULL)
4790 ctxt->error(ctxt->userData, "Element %s is not empty\n",
4791 elem->name);
4792 return(ctxt->err);
4793 }
4794 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
4795 (elemDecl->value != NULL)) {
4796 ctxt->err = XML_SCHEMAS_ERR_HAVEDEFAULT;
4797 if (ctxt->error != NULL)
4798 ctxt->error(ctxt->userData,
4799 "Empty element %s cannot get a fixed value\n",
4800 elem->name);
4801 return(ctxt->err);
4802 }
4803 }
4804 } else {
4805 /* 3.3.4: 3.1 */
4806 if (nil != NULL) {
4807 ctxt->err = XML_SCHEMAS_ERR_NOTNILLABLE;
4808 if (ctxt->error != NULL)
4809 ctxt->error(ctxt->userData,
4810 "Element %s with xs:nil but not nillable\n",
4811 elem->name);
4812 xmlFree(nil);
4813 return(ctxt->err);
4814 }
4815 }
4816
4817 /* TODO 3.3.4: 4 if the element carries xs:type*/
4818
4819 ctxt->type = elemDecl->subtypes;
4820 ctxt->node = elem->children;
4821 xmlSchemaValidateContent(ctxt, elem);
4822 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
4823
4824 return(ctxt->err);
4825}
4826
4827
4828/**
4829 * xmlSchemaValidateAttributes:
4830 * @ctxt: a schema validation context
4831 * @elem: an element
4832 * @attributes: the list of attribute declarations
4833 *
4834 * Validate the attributes of an element.
4835 *
4836 * Returns 0 if the element is schemas valid, a positive error code
4837 * number otherwise and -1 in case of internal or API error.
4838 */
4839static int
4840xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
4841 xmlSchemaAttributePtr attributes) {
4842 int i, ret;
4843 xmlAttrPtr attr;
4844 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004845 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004846
4847 if (attributes == NULL)
4848 return(0);
4849 while (attributes != NULL) {
Daniel Veillard13e04c62002-04-23 17:51:29 +00004850 /*
4851 * Handle attribute groups
4852 */
4853 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
4854 group = (xmlSchemaAttributeGroupPtr) attributes;
4855 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
4856 attributes = group->next;
4857 continue;
4858 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004859 for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
4860 attr = ctxt->attr[i].attr;
4861 if (attr == NULL)
4862 continue;
4863 if (!xmlStrEqual(attr->name, attributes->name))
4864 continue;
4865 /*
4866 * TODO: handle the mess about namespaces here.
4867 */
4868 if ((attr->ns != NULL) /* || (attributes->ns != NULL) */) {
4869 TODO
4870 }
4871 if (attributes->subtypes == NULL) {
4872 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4873 if (ctxt->error != NULL)
4874 ctxt->error(ctxt->userData,
4875 "Internal error: attribute %s type not resolved\n",
4876 attr->name);
4877 continue;
4878 }
4879 value = xmlNodeListGetString(elem->doc, attr->children, 1);
4880 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
Daniel Veillard13e04c62002-04-23 17:51:29 +00004881 value);
Daniel Veillard4255d502002-04-16 15:50:10 +00004882 if (ret != 0) {
4883 ctxt->err = XML_SCHEMAS_ERR_ATTRINVALID;
4884 if (ctxt->error != NULL)
4885 ctxt->error(ctxt->userData,
4886 "attribute %s on %s does not match type\n",
4887 attr->name, elem->name);
4888 } else {
4889 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
4890 }
4891 if (value != NULL) {
4892 xmlFree(value);
4893 }
4894 }
4895 attributes = attributes->next;
4896 }
4897 return(ctxt->err);
4898}
4899
4900/**
4901 * xmlSchemaValidateElement:
4902 * @ctxt: a schema validation context
4903 * @elem: an element
4904 *
4905 * Validate an element in a tree
4906 *
4907 * Returns 0 if the element is schemas valid, a positive error code
4908 * number otherwise and -1 in case of internal or API error.
4909 */
4910static int
4911xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem) {
4912 xmlSchemaElementPtr elemDecl;
4913 int ret, attrBase;
4914
4915 if (elem->ns != NULL)
4916 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
4917 elem->name, elem->ns->href, NULL);
4918 else
4919 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
4920 elem->name, NULL, NULL);
4921 /*
4922 * 3.3.4 : 1
4923 */
4924 if (elemDecl == NULL) {
4925 ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
4926 if (ctxt->error != NULL)
4927 ctxt->error(ctxt->userData, "Element %s not declared\n",
4928 elem->name);
4929 return(ctxt->err);
4930 }
4931 if (elemDecl->subtypes == NULL) {
4932 ctxt->err = XML_SCHEMAS_ERR_NOTYPE;
4933 if (ctxt->error != NULL)
4934 ctxt->error(ctxt->userData, "Element %s has no type\n",
4935 elem->name);
4936 return(ctxt->err);
4937 }
4938 /*
4939 * Verify the attributes
4940 */
4941 attrBase = ctxt->attrBase;
4942 ctxt->attrBase = ctxt->attrNr;
4943 xmlSchemaRegisterAttributes(ctxt, elem->properties);
4944 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
4945 /*
4946 * Verify the element content recursively
4947 */
4948 if (elemDecl->contModel != NULL) {
4949 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
4950 (xmlRegExecCallbacks) xmlSchemaValidateCallback,
4951 ctxt);
4952#ifdef DEBUG_AUTOMATA
4953 xmlGenericError(xmlGenericErrorContext,
4954 "====> %s\n", elem->name);
4955#endif
4956 }
4957 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004958 if (elemDecl->contModel != NULL) {
4959 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004960#ifdef DEBUG_AUTOMATA
Daniel Veillard4255d502002-04-16 15:50:10 +00004961 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004962 "====> %s : %d\n", elem->name, ret);
4963#endif
4964 if (ret == 0) {
4965 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
4966 if (ctxt->error != NULL)
4967 ctxt->error(ctxt->userData, "Element %s content check failed\n",
4968 elem->name);
4969 } else if (ret < 0) {
4970 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
4971 if (ctxt->error != NULL)
4972 ctxt->error(ctxt->userData, "Element %s content check failed\n",
4973 elem->name);
4974#ifdef DEBUG_CONTENT
4975 } else {
4976 xmlGenericError(xmlGenericErrorContext,
4977 "Element %s content check succeeded\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004978
4979#endif
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004980 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004981 xmlRegFreeExecCtxt(ctxt->regexp);
4982 }
4983 /*
4984 * Verify that all attributes were Schemas-validated
4985 */
4986 xmlSchemaCheckAttributes(ctxt, elem);
4987 ctxt->attrNr = ctxt->attrBase;
4988 ctxt->attrBase = attrBase;
4989
4990 return(ctxt->err);
4991}
4992
4993/**
4994 * xmlSchemaValidateDocument:
4995 * @ctxt: a schema validation context
4996 * @doc: a parsed document tree
4997 *
4998 * Validate a document tree in memory.
4999 *
5000 * Returns 0 if the document is schemas valid, a positive error code
5001 * number otherwise and -1 in case of internal or API error.
5002 */
5003static int
5004xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5005 xmlNodePtr root;
5006 xmlSchemaElementPtr elemDecl;
5007
5008 root = xmlDocGetRootElement(doc);
5009 if (root == NULL) {
5010 ctxt->err = XML_SCHEMAS_ERR_NOROOT;
5011 if (ctxt->error != NULL)
5012 ctxt->error(ctxt->userData, "document has no root\n");
5013 return(ctxt->err);
5014 }
5015 if (root->ns != NULL)
5016 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5017 root->name, root->ns->href, NULL);
5018 else
5019 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5020 root->name, NULL, NULL);
5021 if (elemDecl == NULL) {
5022 ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
5023 if (ctxt->error != NULL)
5024 ctxt->error(ctxt->userData, "Element %s not declared\n",
5025 root->name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005026 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005027 ctxt->err = XML_SCHEMAS_ERR_NOTTOPLEVEL;
5028 if (ctxt->error != NULL)
5029 ctxt->error(ctxt->userData, "Root element %s not toplevel\n",
5030 root->name);
5031 }
5032 /*
5033 * Okay, start the recursive validation
5034 */
5035 xmlSchemaValidateElement(ctxt, root);
5036
5037 return(ctxt->err);
5038}
5039
5040/************************************************************************
5041 * *
5042 * SAX Validation code *
5043 * *
5044 ************************************************************************/
5045
5046/************************************************************************
5047 * *
5048 * Validation interfaces *
5049 * *
5050 ************************************************************************/
5051
5052/**
5053 * xmlSchemaNewValidCtxt:
5054 * @schema: a precompiled XML Schemas
5055 *
5056 * Create an XML Schemas validation context based on the given schema
5057 *
5058 * Returns the validation context or NULL in case of error
5059 */
5060xmlSchemaValidCtxtPtr
5061xmlSchemaNewValidCtxt(xmlSchemaPtr schema) {
5062 xmlSchemaValidCtxtPtr ret;
5063
5064 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
5065 if (ret == NULL) {
5066 xmlGenericError(xmlGenericErrorContext,
5067 "Failed to allocate new schama validation context\n");
5068 return (NULL);
5069 }
5070 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
5071 ret->schema = schema;
5072 ret->attrNr = 0;
5073 ret->attrMax = 10;
5074 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
5075 sizeof(xmlSchemaAttrState));
5076 if (ret->attr == NULL) {
5077 free(ret);
5078 return(NULL);
5079 }
5080 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
5081 return (ret);
5082}
5083
5084/**
5085 * xmlSchemaFreeValidCtxt:
5086 * @ctxt: the schema validation context
5087 *
5088 * Free the resources associated to the schema validation context
5089 */
5090void
5091xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) {
5092 if (ctxt == NULL)
5093 return;
5094 if (ctxt->attr != NULL)
5095 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00005096 if (ctxt->value != NULL)
5097 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005098 xmlFree(ctxt);
5099}
5100
5101/**
5102 * xmlSchemaSetValidErrors:
5103 * @ctxt: a schema validation context
5104 * @err: the error function
5105 * @warn: the warning function
5106 * @ctxt: the functions context
5107 *
5108 * Set the error and warning callback informations
5109 */
5110void
5111xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
5112 xmlSchemaValidityErrorFunc err,
5113 xmlSchemaValidityWarningFunc warn, void *ctx) {
5114 if (ctxt == NULL)
5115 return;
5116 ctxt->error = err;
5117 ctxt->warning = warn;
5118 ctxt->userData = ctx;
5119}
5120
5121/**
5122 * xmlSchemaValidateDoc:
5123 * @ctxt: a schema validation context
5124 * @doc: a parsed document tree
5125 *
5126 * Validate a document tree in memory.
5127 *
5128 * Returns 0 if the document is schemas valid, a positive error code
5129 * number otherwise and -1 in case of internal or API error.
5130 */
5131int
5132xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5133 int ret;
5134
5135 if ((ctxt == NULL) || (doc == NULL))
5136 return(-1);
5137
5138 ctxt->doc = doc;
5139 ret = xmlSchemaValidateDocument(ctxt, doc);
5140 return(ret);
5141}
5142
5143/**
5144 * xmlSchemaValidateStream:
5145 * @ctxt: a schema validation context
5146 * @input: the input to use for reading the data
5147 * @enc: an optional encoding information
5148 * @sax: a SAX handler for the resulting events
5149 * @user_data: the context to provide to the SAX handler.
5150 *
5151 * Validate a document tree in memory.
5152 *
5153 * Returns 0 if the document is schemas valid, a positive error code
5154 * number otherwise and -1 in case of internal or API error.
5155 */
5156int
5157xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
5158 xmlParserInputBufferPtr input, xmlCharEncoding enc,
5159 xmlSAXHandlerPtr sax, void *user_data) {
5160 if ((ctxt == NULL) || (input == NULL))
5161 return(-1);
5162 ctxt->input = input;
5163 ctxt->enc = enc;
5164 ctxt->sax = sax;
5165 ctxt->user_data = user_data;
5166 TODO
5167 return(0);
5168}
5169
5170#endif /* LIBXML_SCHEMAS_ENABLED */