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