missing project/build files
[client-tools.git] / src / external / 3rd / library / libxml / xmlschemas.c
blob773fe6e96d9a1f01e20d068df394d0ce7333f08d
1 /*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
5 * See Copyright for the status of this software.
7 * Daniel Veillard <veillard@redhat.com>
8 */
10 #define IN_LIBXML
11 #include "libxml.h"
13 #ifdef LIBXML_SCHEMAS_ENABLED
15 #include <string.h>
16 #include <libxml/xmlmemory.h>
17 #include <libxml/parser.h>
18 #include <libxml/parserInternals.h>
19 #include <libxml/hash.h>
20 #include <libxml/uri.h>
22 #include <libxml/xmlschemas.h>
23 #include <libxml/schemasInternals.h>
24 #include <libxml/xmlschemastypes.h>
25 #include <libxml/xmlautomata.h>
26 #include <libxml/xmlregexp.h>
28 #define DEBUG 1 /* very verbose output */
29 #define DEBUG_CONTENT 1
30 #define DEBUG_TYPE 1
31 /* #define DEBUG_CONTENT_REGEXP 1 */
32 /* #define DEBUG_AUTOMATA 1 */
34 #define UNBOUNDED (1 << 30)
35 #define TODO \
36 xmlGenericError(xmlGenericErrorContext, \
37 "Unimplemented block at %s:%d\n", \
38 __FILE__, __LINE__);
40 #define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
43 * The XML Schemas namespaces
45 static const xmlChar *xmlSchemaNs = (const xmlChar *)
46 "http://www.w3.org/2001/XMLSchema";
48 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
49 "http://www.w3.org/2001/XMLSchema-instance";
51 #define IS_SCHEMA(node, type) \
52 ((node != NULL) && (node->ns != NULL) && \
53 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
54 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
56 #define XML_SCHEMAS_PARSE_ERROR 1
58 struct _xmlSchemaParserCtxt {
59 void *userData; /* user specific data block */
60 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
61 xmlSchemaValidityWarningFunc warning;/* the callback in case of warning */
62 xmlSchemaValidError err;
64 xmlSchemaPtr schema; /* The schema in use */
65 xmlChar *container; /* the current element, group, ... */
66 int counter;
68 xmlChar *URL;
69 xmlDocPtr doc;
71 const char *buffer;
72 int size;
75 * Used to build complex element content models
77 xmlAutomataPtr am;
78 xmlAutomataStatePtr start;
79 xmlAutomataStatePtr end;
80 xmlAutomataStatePtr state;
84 #define XML_SCHEMAS_ATTR_UNKNOWN 1
85 #define XML_SCHEMAS_ATTR_CHECKED 2
87 typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
88 typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
89 struct _xmlSchemaAttrState {
90 xmlAttrPtr attr;
91 int state;
94 /**
95 * xmlSchemaValidCtxt:
97 * A Schemas validation context
100 struct _xmlSchemaValidCtxt {
101 void *userData; /* user specific data block */
102 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
103 xmlSchemaValidityWarningFunc warning;/* the callback in case of warning */
105 xmlSchemaPtr schema; /* The schema in use */
106 xmlDocPtr doc;
107 xmlParserInputBufferPtr input;
108 xmlCharEncoding enc;
109 xmlSAXHandlerPtr sax;
110 void *user_data;
112 xmlDocPtr myDoc;
113 int err;
115 xmlNodePtr node;
116 xmlSchemaTypePtr type;
118 xmlRegExecCtxtPtr regexp;
119 xmlSchemaValPtr value;
121 int attrNr;
122 int attrBase;
123 int attrMax;
124 xmlSchemaAttrStatePtr attr;
128 /************************************************************************
130 * Some predeclarations *
132 ************************************************************************/
133 static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
134 xmlSchemaTypePtr type,
135 xmlChar *value);
137 /************************************************************************
139 * Allocation functions *
141 ************************************************************************/
144 * xmlSchemaNewSchema:
145 * @ctxt: a schema validation context (optional)
147 * Allocate a new Schema structure.
149 * Returns the newly allocated structure or NULL in case or error
151 static xmlSchemaPtr
152 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
154 xmlSchemaPtr ret;
156 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
157 if (ret == NULL) {
158 if ((ctxt != NULL) && (ctxt->error != NULL))
159 ctxt->error(ctxt->userData, "Out of memory\n");
160 return (NULL);
162 memset(ret, 0, sizeof(xmlSchema));
164 return (ret);
168 * xmlSchemaNewFacet:
169 * @ctxt: a schema validation context (optional)
171 * Allocate a new Facet structure.
173 * Returns the newly allocated structure or NULL in case or error
175 static xmlSchemaFacetPtr
176 xmlSchemaNewFacet(xmlSchemaParserCtxtPtr ctxt)
178 xmlSchemaFacetPtr ret;
180 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
181 if (ret == NULL) {
182 if ((ctxt != NULL) && (ctxt->error != NULL))
183 ctxt->error(ctxt->userData, "Out of memory\n");
184 return (NULL);
186 memset(ret, 0, sizeof(xmlSchemaFacet));
188 return (ret);
192 * xmlSchemaNewAnnot:
193 * @ctxt: a schema validation context (optional)
194 * @node: a node
196 * Allocate a new annotation structure.
198 * Returns the newly allocated structure or NULL in case or error
200 static xmlSchemaAnnotPtr
201 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
203 xmlSchemaAnnotPtr ret;
205 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
206 if (ret == NULL) {
207 if ((ctxt != NULL) && (ctxt->error != NULL))
208 ctxt->error(ctxt->userData, "Out of memory\n");
209 return (NULL);
211 memset(ret, 0, sizeof(xmlSchemaAnnot));
212 ret->content = node;
213 return (ret);
217 * xmlSchemaFreeAnnot:
218 * @annot: a schema type structure
220 * Deallocate a annotation structure
222 static void
223 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
225 if (annot == NULL)
226 return;
227 xmlFree(annot);
231 * xmlSchemaFreeNotation:
232 * @schema: a schema notation structure
234 * Deallocate a Schema Notation structure.
236 static void
237 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
239 if (nota == NULL)
240 return;
241 if (nota->name != NULL)
242 xmlFree((xmlChar *) nota->name);
243 xmlFree(nota);
247 * xmlSchemaFreeAttribute:
248 * @schema: a schema attribute structure
250 * Deallocate a Schema Attribute structure.
252 static void
253 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
255 if (attr == NULL)
256 return;
257 if (attr->name != NULL)
258 xmlFree((xmlChar *) attr->name);
259 if (attr->ref != NULL)
260 xmlFree((xmlChar *) attr->ref);
261 if (attr->refNs != NULL)
262 xmlFree((xmlChar *) attr->refNs);
263 if (attr->typeName != NULL)
264 xmlFree((xmlChar *) attr->typeName);
265 if (attr->typeNs != NULL)
266 xmlFree((xmlChar *) attr->typeNs);
267 xmlFree(attr);
271 * xmlSchemaFreeAttributeGroup:
272 * @schema: a schema attribute group structure
274 * Deallocate a Schema Attribute Group structure.
276 static void
277 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
279 if (attr == NULL)
280 return;
281 if (attr->name != NULL)
282 xmlFree((xmlChar *) attr->name);
283 xmlFree(attr);
287 * xmlSchemaFreeElement:
288 * @schema: a schema element structure
290 * Deallocate a Schema Element structure.
292 static void
293 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
295 if (elem == NULL)
296 return;
297 if (elem->name != NULL)
298 xmlFree((xmlChar *) elem->name);
299 if (elem->namedType != NULL)
300 xmlFree((xmlChar *) elem->namedType);
301 if (elem->namedTypeNs != NULL)
302 xmlFree((xmlChar *) elem->namedTypeNs);
303 if (elem->ref != NULL)
304 xmlFree((xmlChar *) elem->ref);
305 if (elem->refNs != NULL)
306 xmlFree((xmlChar *) elem->refNs);
307 if (elem->annot != NULL)
308 xmlSchemaFreeAnnot(elem->annot);
309 if (elem->contModel != NULL)
310 xmlRegFreeRegexp(elem->contModel);
311 xmlFree(elem);
315 * xmlSchemaFreeFacet:
316 * @facet: a schema facet structure
318 * Deallocate a Schema Facet structure.
320 static void
321 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
323 if (facet == NULL)
324 return;
325 if (facet->value != NULL)
326 xmlFree((xmlChar *) facet->value);
327 if (facet->id != NULL)
328 xmlFree((xmlChar *) facet->id);
329 if (facet->val != NULL)
330 xmlSchemaFreeValue(facet->val);
331 if (facet->regexp != NULL)
332 xmlRegFreeRegexp(facet->regexp);
333 if (facet->annot != NULL)
334 xmlSchemaFreeAnnot(facet->annot);
335 xmlFree(facet);
339 * xmlSchemaFreeType:
340 * @type: a schema type structure
342 * Deallocate a Schema Type structure.
344 void
345 xmlSchemaFreeType(xmlSchemaTypePtr type)
347 if (type == NULL)
348 return;
349 if (type->name != NULL)
350 xmlFree((xmlChar *) type->name);
351 if (type->base != NULL)
352 xmlFree((xmlChar *) type->base);
353 if (type->baseNs != NULL)
354 xmlFree((xmlChar *) type->baseNs);
355 if (type->annot != NULL)
356 xmlSchemaFreeAnnot(type->annot);
357 if (type->facets != NULL) {
358 xmlSchemaFacetPtr facet, next;
360 facet = type->facets;
361 while (facet != NULL) {
362 next = facet->next;
363 xmlSchemaFreeFacet(facet);
364 facet = next;
367 xmlFree(type);
371 * xmlSchemaFree:
372 * @schema: a schema structure
374 * Deallocate a Schema structure.
376 void
377 xmlSchemaFree(xmlSchemaPtr schema)
379 if (schema == NULL)
380 return;
382 if (schema->name != NULL)
383 xmlFree((xmlChar *) schema->name);
384 if (schema->notaDecl != NULL)
385 xmlHashFree(schema->notaDecl,
386 (xmlHashDeallocator) xmlSchemaFreeNotation);
387 if (schema->attrDecl != NULL)
388 xmlHashFree(schema->attrDecl,
389 (xmlHashDeallocator) xmlSchemaFreeAttribute);
390 if (schema->attrgrpDecl != NULL)
391 xmlHashFree(schema->attrgrpDecl,
392 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
393 if (schema->elemDecl != NULL)
394 xmlHashFree(schema->elemDecl,
395 (xmlHashDeallocator) xmlSchemaFreeElement);
396 if (schema->typeDecl != NULL)
397 xmlHashFree(schema->typeDecl,
398 (xmlHashDeallocator) xmlSchemaFreeType);
399 if (schema->annot != NULL)
400 xmlSchemaFreeAnnot(schema->annot);
401 if (schema->doc != NULL)
402 xmlFreeDoc(schema->doc);
404 xmlFree(schema);
407 /************************************************************************
409 * Error functions *
411 ************************************************************************/
414 * xmlSchemaErrorContext:
415 * @ctxt: the parsing context
416 * @schema: the schema being built
417 * @node: the node being processed
418 * @child: the child being processed
420 * Dump a SchemaType structure
422 static void
423 xmlSchemaErrorContext(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
424 xmlNodePtr node, xmlNodePtr child)
426 int line = 0;
427 const xmlChar *file = NULL;
428 const xmlChar *name = NULL;
429 const char *type = "error";
431 if ((ctxt == NULL) || (ctxt->error == NULL))
432 return;
434 if (child != NULL)
435 node = child;
437 if (node != NULL) {
438 if ((node->type == XML_DOCUMENT_NODE) ||
439 (node->type == XML_HTML_DOCUMENT_NODE)) {
440 xmlDocPtr doc = (xmlDocPtr) node;
442 file = doc->URL;
443 } else {
445 * Try to find contextual informations to report
447 if (node->type == XML_ELEMENT_NODE) {
448 line = (int) node->content;
449 } else if ((node->prev != NULL) &&
450 (node->prev->type == XML_ELEMENT_NODE)) {
451 line = (int) node->prev->content;
452 } else if ((node->parent != NULL) &&
453 (node->parent->type == XML_ELEMENT_NODE)) {
454 line = (int) node->parent->content;
456 if ((node->doc != NULL) && (node->doc->URL != NULL))
457 file = node->doc->URL;
458 if (node->name != NULL)
459 name = node->name;
463 if (ctxt != NULL)
464 type = "compilation error";
465 else if (schema != NULL)
466 type = "runtime error";
468 if ((file != NULL) && (line != 0) && (name != NULL))
469 ctxt->error(ctxt->userData, "%s: file %s line %d element %s\n",
470 type, file, line, name);
471 else if ((file != NULL) && (name != NULL))
472 ctxt->error(ctxt->userData, "%s: file %s element %s\n",
473 type, file, name);
474 else if ((file != NULL) && (line != 0))
475 ctxt->error(ctxt->userData, "%s: file %s line %d\n", type, file, line);
476 else if (file != NULL)
477 ctxt->error(ctxt->userData, "%s: file %s\n", type, file);
478 else if (name != NULL)
479 ctxt->error(ctxt->userData, "%s: element %s\n", type, name);
480 else
481 ctxt->error(ctxt->userData, "%s\n", type);
484 /************************************************************************
486 * Debug functions *
488 ************************************************************************/
491 * xmlSchemaElementDump:
492 * @elem: an element
493 * @output: the file output
495 * Dump the element
497 static void
498 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
499 const xmlChar *name ATTRIBUTE_UNUSED,
500 const xmlChar *context ATTRIBUTE_UNUSED,
501 const xmlChar *namespace ATTRIBUTE_UNUSED)
503 if (elem == NULL)
504 return;
506 fprintf(output, "Element ");
507 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
508 fprintf(output, "toplevel ");
509 fprintf(output, ": %s ", elem->name);
510 if (namespace != NULL)
511 fprintf(output, "namespace '%s' ", namespace);
513 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
514 fprintf(output, "nillable ");
515 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
516 fprintf(output, "global ");
517 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
518 fprintf(output, "default ");
519 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
520 fprintf(output, "fixed ");
521 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
522 fprintf(output, "abstract ");
523 if (elem->flags & XML_SCHEMAS_ELEM_REF)
524 fprintf(output, "ref '%s' ", elem->ref);
525 if (elem->id != NULL)
526 fprintf(output, "id '%s' ", elem->id);
527 fprintf(output, "\n");
528 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
529 fprintf(output, " ");
530 if (elem->minOccurs != 1)
531 fprintf(output, "min: %d ", elem->minOccurs);
532 if (elem->maxOccurs >= UNBOUNDED)
533 fprintf(output, "max: unbounded\n");
534 else if (elem->maxOccurs != 1)
535 fprintf(output, "max: %d\n", elem->maxOccurs);
536 else
537 fprintf(output, "\n");
539 if (elem->namedType != NULL) {
540 fprintf(output, " type: %s", elem->namedType);
541 if (elem->namedTypeNs != NULL)
542 fprintf(output, " ns %s\n", elem->namedTypeNs);
543 else
544 fprintf(output, "\n");
546 if (elem->substGroup != NULL) {
547 fprintf(output, " substitutionGroup: %s", elem->substGroup);
548 if (elem->substGroupNs != NULL)
549 fprintf(output, " ns %s\n", elem->substGroupNs);
550 else
551 fprintf(output, "\n");
553 if (elem->value != NULL)
554 fprintf(output, " default: %s", elem->value);
558 * xmlSchemaAnnotDump:
559 * @output: the file output
560 * @annot: a annotation
562 * Dump the annotation
564 static void
565 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
567 xmlChar *content;
569 if (annot == NULL)
570 return;
572 content = xmlNodeGetContent(annot->content);
573 if (content != NULL) {
574 fprintf(output, " Annot: %s\n", content);
575 xmlFree(content);
576 } else
577 fprintf(output, " Annot: empty\n");
581 * xmlSchemaTypeDump:
582 * @output: the file output
583 * @type: a type structure
585 * Dump a SchemaType structure
587 static void
588 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
590 if (type == NULL) {
591 fprintf(output, "Type: NULL\n");
592 return;
594 fprintf(output, "Type: ");
595 if (type->name != NULL)
596 fprintf(output, "%s, ", type->name);
597 else
598 fprintf(output, "no name");
599 switch (type->type) {
600 case XML_SCHEMA_TYPE_BASIC:
601 fprintf(output, "basic ");
602 break;
603 case XML_SCHEMA_TYPE_SIMPLE:
604 fprintf(output, "simple ");
605 break;
606 case XML_SCHEMA_TYPE_COMPLEX:
607 fprintf(output, "complex ");
608 break;
609 case XML_SCHEMA_TYPE_SEQUENCE:
610 fprintf(output, "sequence ");
611 break;
612 case XML_SCHEMA_TYPE_CHOICE:
613 fprintf(output, "choice ");
614 break;
615 case XML_SCHEMA_TYPE_ALL:
616 fprintf(output, "all ");
617 break;
618 case XML_SCHEMA_TYPE_UR:
619 fprintf(output, "ur ");
620 break;
621 case XML_SCHEMA_TYPE_RESTRICTION:
622 fprintf(output, "restriction ");
623 break;
624 case XML_SCHEMA_TYPE_EXTENSION:
625 fprintf(output, "extension ");
626 break;
627 default:
628 fprintf(output, "unknowntype%d ", type->type);
629 break;
631 if (type->base != NULL) {
632 fprintf(output, "base %s, ", type->base);
634 switch (type->contentType) {
635 case XML_SCHEMA_CONTENT_UNKNOWN:
636 fprintf(output, "unknown ");
637 break;
638 case XML_SCHEMA_CONTENT_EMPTY:
639 fprintf(output, "empty ");
640 break;
641 case XML_SCHEMA_CONTENT_ELEMENTS:
642 fprintf(output, "element ");
643 break;
644 case XML_SCHEMA_CONTENT_MIXED:
645 fprintf(output, "mixed ");
646 break;
647 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
648 fprintf(output, "mixed_or_elems ");
649 break;
650 case XML_SCHEMA_CONTENT_BASIC:
651 fprintf(output, "basic ");
652 break;
653 case XML_SCHEMA_CONTENT_SIMPLE:
654 fprintf(output, "simple ");
655 break;
656 case XML_SCHEMA_CONTENT_ANY:
657 fprintf(output, "any ");
658 break;
660 fprintf(output, "\n");
661 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
662 fprintf(output, " ");
663 if (type->minOccurs != 1)
664 fprintf(output, "min: %d ", type->minOccurs);
665 if (type->maxOccurs >= UNBOUNDED)
666 fprintf(output, "max: unbounded\n");
667 else if (type->maxOccurs != 1)
668 fprintf(output, "max: %d\n", type->maxOccurs);
669 else
670 fprintf(output, "\n");
672 if (type->annot != NULL)
673 xmlSchemaAnnotDump(output, type->annot);
674 if (type->subtypes != NULL) {
675 xmlSchemaTypePtr sub = type->subtypes;
677 fprintf(output, " subtypes: ");
678 while (sub != NULL) {
679 fprintf(output, "%s ", sub->name);
680 sub = sub->next;
682 fprintf(output, "\n");
688 * xmlSchemaDump:
689 * @output: the file output
690 * @schema: a schema structure
692 * Dump a Schema structure.
694 void
695 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
697 if (schema == NULL) {
698 fprintf(output, "Schemas: NULL\n");
699 return;
701 fprintf(output, "Schemas: ");
702 if (schema->name != NULL)
703 fprintf(output, "%s, ", schema->name);
704 else
705 fprintf(output, "no name, ");
706 if (schema->targetNamespace != NULL)
707 fprintf(output, "%s", schema->targetNamespace);
708 else
709 fprintf(output, "no target namespace");
710 fprintf(output, "\n");
711 if (schema->annot != NULL)
712 xmlSchemaAnnotDump(output, schema->annot);
714 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
715 output);
716 xmlHashScanFull(schema->elemDecl,
717 (xmlHashScannerFull) xmlSchemaElementDump, output);
720 /************************************************************************
722 * Parsing functions *
724 ************************************************************************/
727 * xmlSchemaGetType:
728 * @schema: the schemas context
729 * @name: the type name
730 * @ns: the type namespace
732 * Lookup a type in the schemas or the predefined types
734 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
736 static xmlSchemaTypePtr
737 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
738 const xmlChar * namespace) {
739 xmlSchemaTypePtr ret;
741 if (name == NULL)
742 return(NULL);
743 if (schema != NULL) {
744 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
745 if (ret != NULL)
746 return(ret);
748 ret = xmlSchemaGetPredefinedType(name, namespace);
749 #ifdef DEBUG
750 if (ret == NULL) {
751 if (namespace == NULL)
752 fprintf(stderr, "Unable to lookup type %s", name);
753 else
754 fprintf(stderr, "Unable to lookup type %s:%s", name, namespace);
756 #endif
757 return(ret);
760 /************************************************************************
762 * Parsing functions *
764 ************************************************************************/
766 #define IS_BLANK_NODE(n) \
767 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
770 * xmlSchemaIsBlank:
771 * @str: a string
773 * Check if a string is ignorable
775 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
777 static int
778 xmlSchemaIsBlank(xmlChar *str) {
779 if (str == NULL)
780 return(1);
781 while (*str != 0) {
782 if (!(IS_BLANK(*str))) return(0);
783 str++;
785 return(1);
789 * xmlSchemaAddNotation:
790 * @ctxt: a schema validation context
791 * @schema: the schema being built
792 * @name: the item name
794 * Add an XML schema Attrribute declaration
795 * *WARNING* this interface is highly subject to change
797 * Returns the new struture or NULL in case of error
799 static xmlSchemaNotationPtr
800 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
801 const xmlChar * name)
803 xmlSchemaNotationPtr ret = NULL;
804 int val;
806 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
807 return (NULL);
809 if (schema->notaDecl == NULL)
810 schema->notaDecl = xmlHashCreate(10);
811 if (schema->notaDecl == NULL)
812 return (NULL);
814 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
815 if (ret == NULL) {
816 if ((ctxt != NULL) && (ctxt->error != NULL))
817 ctxt->error(ctxt->userData, "Out of memory\n");
818 return (NULL);
820 memset(ret, 0, sizeof(xmlSchemaNotation));
821 ret->name = xmlStrdup(name);
822 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
823 ret);
824 if (val != 0) {
825 if ((ctxt != NULL) && (ctxt->error != NULL))
826 ctxt->error(ctxt->userData, "Could not add notation %s\n",
827 name);
828 xmlFree((char *) ret->name);
829 xmlFree(ret);
830 return (NULL);
832 return (ret);
837 * xmlSchemaAddAttribute:
838 * @ctxt: a schema validation context
839 * @schema: the schema being built
840 * @name: the item name
841 * @container: the container's name
843 * Add an XML schema Attrribute declaration
844 * *WARNING* this interface is highly subject to change
846 * Returns the new struture or NULL in case of error
848 static xmlSchemaAttributePtr
849 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
850 const xmlChar * name)
852 xmlSchemaAttributePtr ret = NULL;
853 int val;
855 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
856 return (NULL);
858 if (schema->attrDecl == NULL)
859 schema->attrDecl = xmlHashCreate(10);
860 if (schema->attrDecl == NULL)
861 return (NULL);
863 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
864 if (ret == NULL) {
865 if ((ctxt != NULL) && (ctxt->error != NULL))
866 ctxt->error(ctxt->userData, "Out of memory\n");
867 return (NULL);
869 memset(ret, 0, sizeof(xmlSchemaAttribute));
870 ret->name = xmlStrdup(name);
871 val = xmlHashAddEntry3(schema->attrDecl, name,
872 schema->targetNamespace, ctxt->container, ret);
873 if (val != 0) {
874 if ((ctxt != NULL) && (ctxt->error != NULL))
875 ctxt->error(ctxt->userData, "Could not add attribute %s\n",
876 name);
877 xmlFree((char *) ret->name);
878 xmlFree(ret);
879 return (NULL);
881 return (ret);
885 * xmlSchemaAddAttributeGroup:
886 * @ctxt: a schema validation context
887 * @schema: the schema being built
888 * @name: the item name
890 * Add an XML schema Attrribute Group declaration
892 * Returns the new struture or NULL in case of error
894 static xmlSchemaAttributeGroupPtr
895 xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
896 const xmlChar * name)
898 xmlSchemaAttributeGroupPtr ret = NULL;
899 int val;
901 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
902 return (NULL);
904 if (schema->attrgrpDecl == NULL)
905 schema->attrgrpDecl = xmlHashCreate(10);
906 if (schema->attrgrpDecl == NULL)
907 return (NULL);
909 ret = (xmlSchemaAttributeGroupPtr) xmlMalloc(sizeof(xmlSchemaAttributeGroup));
910 if (ret == NULL) {
911 if ((ctxt != NULL) && (ctxt->error != NULL))
912 ctxt->error(ctxt->userData, "Out of memory\n");
913 return (NULL);
915 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
916 ret->name = xmlStrdup(name);
917 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
918 schema->targetNamespace, ctxt->container, ret);
919 if (val != 0) {
920 if ((ctxt != NULL) && (ctxt->error != NULL))
921 ctxt->error(ctxt->userData, "Could not add attribute group %s\n",
922 name);
923 xmlFree((char *) ret->name);
924 xmlFree(ret);
925 return (NULL);
927 return (ret);
931 * xmlSchemaAddElement:
932 * @ctxt: a schema validation context
933 * @schema: the schema being built
934 * @name: the type name
935 * @namespace: the type namespace
937 * Add an XML schema Element declaration
938 * *WARNING* this interface is highly subject to change
940 * Returns the new struture or NULL in case of error
942 static xmlSchemaElementPtr
943 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
944 const xmlChar * name, const xmlChar * namespace)
946 xmlSchemaElementPtr ret = NULL;
947 int val;
949 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
950 return (NULL);
952 if (schema->elemDecl == NULL)
953 schema->elemDecl = xmlHashCreate(10);
954 if (schema->elemDecl == NULL)
955 return (NULL);
957 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
958 if (ret == NULL) {
959 if ((ctxt != NULL) && (ctxt->error != NULL))
960 ctxt->error(ctxt->userData, "Out of memory\n");
961 return (NULL);
963 memset(ret, 0, sizeof(xmlSchemaElement));
964 ret->name = xmlStrdup(name);
965 val = xmlHashAddEntry3(schema->elemDecl, name,
966 namespace, ctxt->container, ret);
967 if (val != 0) {
968 char buf[100];
970 snprintf(buf, 99, "privatieelem%d", ctxt->counter++ + 1);
971 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
972 namespace, ret);
973 if (val != 0) {
974 if ((ctxt != NULL) && (ctxt->error != NULL))
975 ctxt->error(ctxt->userData, "Could not add element %s\n",
976 name);
977 xmlFree((char *) ret->name);
978 xmlFree(ret);
979 return (NULL);
982 return (ret);
986 * xmlSchemaAddType:
987 * @ctxt: a schema validation context
988 * @schema: the schema being built
989 * @name: the item name
991 * Add an XML schema Simple Type definition
992 * *WARNING* this interface is highly subject to change
994 * Returns the new struture or NULL in case of error
996 static xmlSchemaTypePtr
997 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
998 const xmlChar * name)
1000 xmlSchemaTypePtr ret = NULL;
1001 int val;
1003 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1004 return (NULL);
1006 if (schema->typeDecl == NULL)
1007 schema->typeDecl = xmlHashCreate(10);
1008 if (schema->typeDecl == NULL)
1009 return (NULL);
1011 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1012 if (ret == NULL) {
1013 if ((ctxt != NULL) && (ctxt->error != NULL))
1014 ctxt->error(ctxt->userData, "Out of memory\n");
1015 return (NULL);
1017 memset(ret, 0, sizeof(xmlSchemaType));
1018 ret->name = xmlStrdup(name);
1019 val = xmlHashAddEntry2(schema->typeDecl, name, schema->targetNamespace,
1020 ret);
1021 if (val != 0) {
1022 if ((ctxt != NULL) && (ctxt->error != NULL))
1023 ctxt->error(ctxt->userData, "Could not add type %s\n", name);
1024 xmlFree((char *) ret->name);
1025 xmlFree(ret);
1026 return (NULL);
1028 ret->minOccurs = 1;
1029 ret->maxOccurs = 1;
1031 return (ret);
1034 /************************************************************************
1036 * Utilities for parsing *
1038 ************************************************************************/
1041 * xmlGetQNameProp:
1042 * @ctxt: a schema validation context
1043 * @node: a subtree containing XML Schema informations
1044 * @name: the attribute name
1045 * @namespace: the result namespace if any
1047 * Extract a QName Attribute value
1049 * Returns the NCName or NULL if not found, and also update @namespace
1050 * with the namespace URI
1052 static xmlChar *
1053 xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1054 const char *name,
1055 xmlChar **namespace) {
1056 xmlChar *val, *ret, *prefix;
1057 xmlNsPtr ns;
1060 if (namespace != NULL)
1061 *namespace = NULL;
1062 val = xmlGetProp(node, (const xmlChar *) name);
1063 if (val == NULL)
1064 return(NULL);
1066 ret = xmlSplitQName2(val, &prefix);
1067 if (ret == NULL)
1068 return(val);
1069 xmlFree(val);
1071 ns = xmlSearchNs(node->doc, node, prefix);
1072 if (ns == NULL) {
1073 xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1074 if ((ctxt != NULL) && (ctxt->error != NULL))
1075 ctxt->error(ctxt->userData,
1076 "Attribute %s: the QName prefix %s is undefined\n",
1077 name, prefix);
1078 } else {
1079 *namespace = xmlStrdup(ns->href);
1081 xmlFree(prefix);
1082 return(ret);
1086 * xmlGetMaxOccurs:
1087 * @ctxt: a schema validation context
1088 * @node: a subtree containing XML Schema informations
1090 * Get the maxOccurs property
1092 * Returns the default if not found, or the value
1094 static int
1095 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) {
1096 xmlChar *val, *cur;
1097 int ret = 0;
1099 val = xmlGetProp(node, (const xmlChar *) "maxOccurs");
1100 if (val == NULL)
1101 return(1);
1103 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
1104 xmlFree(val);
1105 return(UNBOUNDED); /* encoding it with -1 might be another option */
1108 cur = val;
1109 while (IS_BLANK(*cur)) cur++;
1110 while ((*cur >= '0') && (*cur <= '9')) {
1111 ret = ret * 10 + (*cur - '0');
1112 cur++;
1114 while (IS_BLANK(*cur)) cur++;
1115 if (*cur != 0) {
1116 xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1117 if ((ctxt != NULL) && (ctxt->error != NULL))
1118 ctxt->error(ctxt->userData, "invalid value for minOccurs: %s\n",
1119 val);
1120 xmlFree(val);
1121 return(1);
1123 xmlFree(val);
1124 return(ret);
1128 * xmlGetMinOccurs:
1129 * @ctxt: a schema validation context
1130 * @node: a subtree containing XML Schema informations
1132 * Get the minOccurs property
1134 * Returns the default if not found, or the value
1136 static int
1137 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) {
1138 xmlChar *val, *cur;
1139 int ret = 0;
1141 val = xmlGetProp(node, (const xmlChar *) "minOccurs");
1142 if (val == NULL)
1143 return(1);
1145 cur = val;
1146 while (IS_BLANK(*cur)) cur++;
1147 while ((*cur >= '0') && (*cur <= '9')) {
1148 ret = ret * 10 + (*cur - '0');
1149 cur++;
1151 while (IS_BLANK(*cur)) cur++;
1152 if (*cur != 0) {
1153 xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1154 if ((ctxt != NULL) && (ctxt->error != NULL))
1155 ctxt->error(ctxt->userData, "invalid value for minOccurs: %s\n",
1156 val);
1157 xmlFree(val);
1158 return(1);
1160 xmlFree(val);
1161 return(ret);
1165 * xmlGetBooleanProp:
1166 * @ctxt: a schema validation context
1167 * @node: a subtree containing XML Schema informations
1168 * @name: the attribute name
1169 * @def: the default value
1171 * Get is a bolean property is set
1173 * Returns the default if not found, 0 if found to be false,
1174 * 1 if found to be true
1176 static int
1177 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1178 const char *name, int def) {
1179 xmlChar *val;
1181 val = xmlGetProp(node, (const xmlChar *) name);
1182 if (val == NULL)
1183 return(def);
1185 if (xmlStrEqual(val, BAD_CAST"true"))
1186 def = 1;
1187 else if (xmlStrEqual(val, BAD_CAST"false"))
1188 def = 0;
1189 else {
1190 xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1191 if ((ctxt != NULL) && (ctxt->error != NULL))
1192 ctxt->error(ctxt->userData,
1193 "Attribute %s: the value %s is not boolean\n",
1194 name, val);
1196 xmlFree(val);
1197 return(def);
1200 /************************************************************************
1202 * Shema extraction from an Infoset *
1204 ************************************************************************/
1205 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1206 ctxt, xmlSchemaPtr schema,
1207 xmlNodePtr node);
1208 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,
1209 xmlSchemaPtr schema,
1210 xmlNodePtr node);
1211 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,
1212 xmlSchemaPtr schema,
1213 xmlNodePtr node,
1214 int simple);
1215 static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1216 xmlSchemaPtr schema,
1217 xmlNodePtr node);
1218 static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1219 xmlSchemaPtr schema,
1220 xmlNodePtr node);
1221 static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1222 ctxt,
1223 xmlSchemaPtr schema,
1224 xmlNodePtr node);
1225 static xmlSchemaAttributeGroupPtr
1226 xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1227 xmlSchemaPtr schema, xmlNodePtr node);
1228 static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1229 xmlSchemaPtr schema,
1230 xmlNodePtr node);
1231 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1232 xmlSchemaPtr schema,
1233 xmlNodePtr node);
1234 static xmlSchemaAttributePtr
1235 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1236 xmlNodePtr node);
1239 * xmlSchemaParseAttrDecls:
1240 * @ctxt: a schema validation context
1241 * @schema: the schema being built
1242 * @node: a subtree containing XML Schema informations
1243 * @type: the hosting type
1245 * parse a XML schema attrDecls declaration corresponding to
1246 * <!ENTITY % attrDecls
1247 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1249 static xmlNodePtr
1250 xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1251 xmlNodePtr child, xmlSchemaTypePtr type)
1253 xmlSchemaAttributePtr lastattr, attr;
1255 lastattr = NULL;
1256 while ((IS_SCHEMA(child, "attribute")) ||
1257 (IS_SCHEMA(child, "attributeGroup"))) {
1258 attr = NULL;
1259 if (IS_SCHEMA(child, "attribute")) {
1260 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1261 } else if (IS_SCHEMA(child, "attributeGroup")) {
1262 attr = (xmlSchemaAttributePtr)
1263 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1265 if (attr != NULL) {
1266 if (lastattr == NULL) {
1267 type->attributes = attr;
1268 lastattr = attr
1270 } else {
1271 lastattr->next = attr;
1272 lastattr = attr;
1275 child = child->next;
1277 if (IS_SCHEMA(child, "anyAttribute")) {
1278 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1279 if (attr != NULL) {
1280 if (lastattr == NULL) {
1281 type->attributes = attr;
1282 lastattr = attr
1284 } else {
1285 lastattr->next = attr;
1286 lastattr = attr;
1289 child = child->next;
1291 return(child);
1295 * xmlSchemaParseAnnotation:
1296 * @ctxt: a schema validation context
1297 * @schema: the schema being built
1298 * @node: a subtree containing XML Schema informations
1300 * parse a XML schema Attrribute declaration
1301 * *WARNING* this interface is highly subject to change
1303 * Returns -1 in case of error, 0 if the declaration is inproper and
1304 * 1 in case of success.
1306 static xmlSchemaAnnotPtr
1307 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1308 xmlNodePtr node)
1310 xmlSchemaAnnotPtr ret;
1312 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1313 return (NULL);
1314 ret = xmlSchemaNewAnnot(ctxt, node);
1316 return (ret);
1320 * xmlSchemaParseFacet:
1321 * @ctxt: a schema validation context
1322 * @schema: the schema being built
1323 * @node: a subtree containing XML Schema informations
1325 * parse a XML schema Facet declaration
1326 * *WARNING* this interface is highly subject to change
1328 * Returns the new type structure or NULL in case of error
1330 static xmlSchemaFacetPtr
1331 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1332 xmlNodePtr node)
1334 xmlSchemaFacetPtr facet;
1335 xmlNodePtr child = NULL;
1336 xmlChar *value;
1338 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1339 return (NULL);
1341 facet = xmlSchemaNewFacet(ctxt);
1342 if (facet == NULL)
1343 return (NULL);
1344 facet->node = node;
1345 value = xmlGetProp(node, (const xmlChar *) "value");
1346 if (value == NULL) {
1347 xmlSchemaErrorContext(ctxt, schema, node, child);
1348 if ((ctxt != NULL) && (ctxt->error != NULL))
1349 ctxt->error(ctxt->userData, "Facet %s has no value\n", node->name);
1350 xmlSchemaFreeFacet(facet);
1351 return (NULL);
1353 if (IS_SCHEMA(node, "minInclusive")) {
1354 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
1355 } else if (IS_SCHEMA(node, "minExclusive")) {
1356 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
1357 } else if (IS_SCHEMA(node, "maxInclusive")) {
1358 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
1359 } else if (IS_SCHEMA(node, "maxExclusive")) {
1360 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
1361 } else if (IS_SCHEMA(node, "totalDigits")) {
1362 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
1363 } else if (IS_SCHEMA(node, "fractionDigits")) {
1364 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
1365 } else if (IS_SCHEMA(node, "pattern")) {
1366 facet->type = XML_SCHEMA_FACET_PATTERN;
1367 } else if (IS_SCHEMA(node, "enumeration")) {
1368 facet->type = XML_SCHEMA_FACET_ENUMERATION;
1369 } else if (IS_SCHEMA(node, "whiteSpace")) {
1370 facet->type = XML_SCHEMA_FACET_WHITESPACE;
1371 } else if (IS_SCHEMA(node, "length")) {
1372 facet->type = XML_SCHEMA_FACET_LENGTH;
1373 } else if (IS_SCHEMA(node, "maxLength")) {
1374 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1375 } else if (IS_SCHEMA(node, "minLength")) {
1376 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1377 } else {
1378 xmlSchemaErrorContext(ctxt, schema, node, child);
1379 if ((ctxt != NULL) && (ctxt->error != NULL))
1380 ctxt->error(ctxt->userData, "Unknown facet type %s\n", node->name);
1381 xmlSchemaFreeFacet(facet);
1382 return(NULL);
1384 facet->id = xmlGetProp(node, (const xmlChar *) "id");
1385 facet->value = value;
1386 child = node->children;
1388 if (IS_SCHEMA(child, "annotation")) {
1389 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1390 child = child->next;
1392 if (child != NULL) {
1393 xmlSchemaErrorContext(ctxt, schema, node, child);
1394 if ((ctxt != NULL) && (ctxt->error != NULL))
1395 ctxt->error(ctxt->userData,
1396 "Facet %s has unexpected child content\n",
1397 node->name);
1399 return (facet);
1403 * xmlSchemaParseAny:
1404 * @ctxt: a schema validation context
1405 * @schema: the schema being built
1406 * @node: a subtree containing XML Schema informations
1408 * parse a XML schema Any declaration
1409 * *WARNING* this interface is highly subject to change
1411 * Returns the new type structure or NULL in case of error
1413 static xmlSchemaTypePtr
1414 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1415 xmlNodePtr node)
1417 xmlSchemaTypePtr type;
1418 xmlNodePtr child = NULL;
1419 xmlChar name[30];
1421 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1422 return (NULL);
1423 snprintf((char *)name, 30, "any %d", ctxt->counter++ + 1);
1424 type = xmlSchemaAddType(ctxt, schema, name);
1425 if (type == NULL)
1426 return (NULL);
1427 type->node = node;
1428 type->type = XML_SCHEMA_TYPE_ANY;
1429 child = node->children;
1430 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1431 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1433 if (IS_SCHEMA(child, "annotation")) {
1434 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1435 child = child->next;
1437 if (child != NULL) {
1438 xmlSchemaErrorContext(ctxt, schema, node, child);
1439 if ((ctxt != NULL) && (ctxt->error != NULL))
1440 ctxt->error(ctxt->userData,
1441 "Sequence %s has unexpected content\n",
1442 type->name);
1445 return (type);
1449 * xmlSchemaParseNotation:
1450 * @ctxt: a schema validation context
1451 * @schema: the schema being built
1452 * @node: a subtree containing XML Schema informations
1454 * parse a XML schema Notation declaration
1456 * Returns the new structure or NULL in case of error
1458 static xmlSchemaNotationPtr
1459 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1460 xmlNodePtr node)
1462 xmlChar *name;
1463 xmlSchemaNotationPtr ret;
1464 xmlNodePtr child = NULL;
1466 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1467 return (NULL);
1468 name = xmlGetProp(node, (const xmlChar *) "name");
1469 if (name == NULL) {
1470 xmlSchemaErrorContext(ctxt, schema, node, child);
1471 if ((ctxt != NULL) && (ctxt->error != NULL))
1472 ctxt->error(ctxt->userData, "Notation has no name\n");
1473 return (NULL);
1475 ret = xmlSchemaAddNotation(ctxt, schema, name);
1476 if (ret == NULL) {
1477 xmlFree(name);
1478 return (NULL);
1480 child = node->children;
1481 if (IS_SCHEMA(child, "annotation")) {
1482 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1483 child = child->next;
1485 if (child != NULL) {
1486 xmlSchemaErrorContext(ctxt, schema, node, child);
1487 if ((ctxt != NULL) && (ctxt->error != NULL))
1488 ctxt->error(ctxt->userData,
1489 "notation %s has unexpected content\n",
1490 name);
1493 return (ret);
1497 * xmlSchemaParseAnyAttribute:
1498 * @ctxt: a schema validation context
1499 * @schema: the schema being built
1500 * @node: a subtree containing XML Schema informations
1502 * parse a XML schema AnyAttrribute declaration
1503 * *WARNING* this interface is highly subject to change
1505 * Returns an attribute def structure or NULL
1507 static xmlSchemaAttributePtr
1508 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1509 xmlNodePtr node)
1511 xmlChar *processContents;
1512 xmlSchemaAttributePtr ret;
1513 xmlNodePtr child = NULL;
1514 char name[100];
1516 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1517 return (NULL);
1519 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
1520 ret = xmlSchemaAddAttribute(ctxt, schema, (xmlChar *)name);
1521 if (ret == NULL) {
1522 return (NULL);
1524 ret->id = xmlGetProp(node, (const xmlChar *) "id");
1525 processContents = xmlGetProp(node, (const xmlChar *) "processContents");
1526 if ((processContents == NULL) ||
1527 (xmlStrEqual(processContents, (const xmlChar *)"strict"))) {
1528 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1529 } else if (xmlStrEqual(processContents, (const xmlChar *)"skip")) {
1530 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1531 } else if (xmlStrEqual(processContents, (const xmlChar *)"lax")) {
1532 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
1533 } else {
1534 xmlSchemaErrorContext(ctxt, schema, node, child);
1535 if ((ctxt != NULL) && (ctxt->error != NULL))
1536 ctxt->error(ctxt->userData,
1537 "anyAttribute has unexpected content for processContents: %s\n",
1538 processContents);
1539 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1541 if (processContents != NULL)
1542 xmlFree(processContents);
1544 child = node->children;
1545 if (IS_SCHEMA(child, "annotation")) {
1546 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1547 child = child->next;
1549 if (child != NULL) {
1550 xmlSchemaErrorContext(ctxt, schema, node, child);
1551 if ((ctxt != NULL) && (ctxt->error != NULL))
1552 ctxt->error(ctxt->userData,
1553 "anyAttribute %s has unexpected content\n",
1554 name);
1557 return (ret);
1562 * xmlSchemaParseAttribute:
1563 * @ctxt: a schema validation context
1564 * @schema: the schema being built
1565 * @node: a subtree containing XML Schema informations
1567 * parse a XML schema Attrribute declaration
1568 * *WARNING* this interface is highly subject to change
1570 * Returns -1 in case of error, 0 if the declaration is inproper and
1571 * 1 in case of success.
1573 static xmlSchemaAttributePtr
1574 xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1575 xmlNodePtr node)
1577 xmlChar *name, *refNs = NULL, *ref = NULL;
1578 xmlSchemaAttributePtr ret;
1579 xmlNodePtr child = NULL;
1581 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1582 return (NULL);
1583 name = xmlGetProp(node, (const xmlChar *) "name");
1584 if (name == NULL) {
1585 char buf[100];
1587 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1588 if (ref == NULL) {
1589 xmlSchemaErrorContext(ctxt, schema, node, child);
1590 if ((ctxt != NULL) && (ctxt->error != NULL))
1591 ctxt->error(ctxt->userData, "Attribute has no name nor ref\n");
1592 return (NULL);
1594 snprintf(buf, 99, "anonattr%d", ctxt->counter++ + 1);
1595 name = xmlStrdup((xmlChar *) buf);
1597 ret = xmlSchemaAddAttribute(ctxt, schema, name);
1598 if (ret == NULL) {
1599 xmlFree(name);
1600 if (ref != NULL)
1601 xmlFree(ref);
1602 return (NULL);
1604 xmlFree(name);
1605 ret->ref = ref;
1606 ret->refNs = refNs;
1607 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
1608 child = node->children;
1609 if (IS_SCHEMA(child, "annotation")) {
1610 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1611 child = child->next;
1613 if (IS_SCHEMA(child, "simpleType")) {
1614 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1615 child = child->next;
1617 if (child != NULL) {
1618 xmlSchemaErrorContext(ctxt, schema, node, child);
1619 if ((ctxt != NULL) && (ctxt->error != NULL))
1620 ctxt->error(ctxt->userData,
1621 "attribute %s has unexpected content\n",
1622 name);
1625 return (ret);
1629 * xmlSchemaParseAttributeGroup:
1630 * @ctxt: a schema validation context
1631 * @schema: the schema being built
1632 * @node: a subtree containing XML Schema informations
1634 * parse a XML schema Attribute Group declaration
1635 * *WARNING* this interface is highly subject to change
1637 * Returns the attribute group or NULL in case of error.
1639 static xmlSchemaAttributeGroupPtr
1640 xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1641 xmlNodePtr node)
1643 xmlChar *name, *refNs = NULL, *ref = NULL;
1644 xmlSchemaAttributeGroupPtr ret;
1645 xmlSchemaAttributePtr last = NULL, attr;
1646 xmlNodePtr child = NULL;
1647 xmlChar *oldcontainer;
1649 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1650 return (NULL);
1651 oldcontainer = ctxt->container;
1652 name = xmlGetProp(node, (const xmlChar *) "name");
1653 if (name == NULL) {
1654 char buf[100];
1656 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1657 if (ref == NULL) {
1658 xmlSchemaErrorContext(ctxt, schema, node, child);
1659 if ((ctxt != NULL) && (ctxt->error != NULL))
1660 ctxt->error(ctxt->userData,
1661 "AttributeGroup has no name nor ref\n");
1662 return (NULL);
1664 snprintf(buf, 99, "anonattrgroup%d", ctxt->counter++ + 1);
1665 name = xmlStrdup((xmlChar *) buf);
1667 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
1668 if (ret == NULL) {
1669 xmlFree(name);
1670 if (ref != NULL)
1671 xmlFree(ref);
1672 return (NULL);
1674 ret->ref = ref;
1675 ret->refNs = refNs;
1676 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
1677 child = node->children;
1678 ctxt->container = name;
1679 if (IS_SCHEMA(child, "annotation")) {
1680 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1681 child = child->next;
1683 while ((IS_SCHEMA(child, "attribute")) ||
1684 (IS_SCHEMA(child, "attributeGroup"))) {
1685 attr = NULL;
1686 if (IS_SCHEMA(child, "attribute")) {
1687 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1688 } else if (IS_SCHEMA(child, "attributeGroup")) {
1689 attr = (xmlSchemaAttributePtr)
1690 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1692 if (attr != NULL) {
1693 if (last == NULL) {
1694 ret->attributes = attr;
1695 last = attr;
1696 } else {
1697 last->next = attr;
1698 last = attr;
1701 child = child->next;
1703 if (IS_SCHEMA(child, "anyAttribute")) {
1704 TODO
1705 child = child->next;
1707 if (child != NULL) {
1708 xmlSchemaErrorContext(ctxt, schema, node, child);
1709 if ((ctxt != NULL) && (ctxt->error != NULL))
1710 ctxt->error(ctxt->userData,
1711 "attribute group %s has unexpected content\n",
1712 name);
1715 ctxt->container = oldcontainer;
1716 return (ret);
1720 * xmlSchemaParseElement:
1721 * @ctxt: a schema validation context
1722 * @schema: the schema being built
1723 * @node: a subtree containing XML Schema informations
1725 * parse a XML schema Element declaration
1726 * *WARNING* this interface is highly subject to change
1728 * Returns -1 in case of error, 0 if the declaration is inproper and
1729 * 1 in case of success.
1731 static xmlSchemaElementPtr
1732 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1733 xmlNodePtr node, int toplevel)
1735 xmlChar *name, *refNs = NULL, *ref = NULL, *namespace, *fixed;
1736 xmlSchemaElementPtr ret;
1737 xmlNodePtr child = NULL;
1738 xmlChar *oldcontainer;
1740 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1741 return (NULL);
1742 oldcontainer = ctxt->container;
1743 name = xmlGetProp(node, (const xmlChar *) "name");
1744 if (name == NULL) {
1745 char buf[100];
1747 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1748 if (ref == NULL) {
1749 xmlSchemaErrorContext(ctxt, schema, node, child);
1750 if ((ctxt != NULL) && (ctxt->error != NULL))
1751 ctxt->error(ctxt->userData, "Element has no name nor ref\n");
1752 return (NULL);
1754 snprintf(buf, 99, "anonelem%d", ctxt->counter++ + 1);
1755 name = xmlStrdup((xmlChar *) buf);
1757 namespace = xmlGetProp(node, (const xmlChar *) "targetNamespace");
1758 if (namespace == NULL)
1759 ret =
1760 xmlSchemaAddElement(ctxt, schema, name,
1761 schema->targetNamespace);
1762 else
1763 ret = xmlSchemaAddElement(ctxt, schema, name, namespace);
1764 if (namespace != NULL)
1765 xmlFree(namespace);
1766 if (ret == NULL) {
1767 xmlFree(name);
1768 if (ref != NULL)
1769 xmlFree(ref);
1770 return (NULL);
1772 ret->type = XML_SCHEMA_TYPE_ELEMENT;
1773 ret->ref = ref;
1774 ret->refNs = refNs;
1775 if (ref != NULL)
1776 ret->flags |= XML_SCHEMAS_ELEM_REF;
1777 if (toplevel)
1778 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
1779 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
1780 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1781 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
1782 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1783 ctxt->container = name;
1785 ret->id = xmlGetProp(node, BAD_CAST "id");
1786 ret->namedType = xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
1787 ret->substGroup = xmlGetQNameProp(ctxt, node, "substitutionGroup",
1788 &(ret->substGroupNs));
1789 fixed = xmlGetProp(node, BAD_CAST "fixed");
1790 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
1791 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1793 ret->value = xmlGetProp(node, BAD_CAST "default");
1794 if ((ret->value != NULL) && (fixed != NULL)) {
1795 xmlSchemaErrorContext(ctxt, schema, node, child);
1796 ctxt->error(ctxt->userData,
1797 "Element %s has both default and fixed\n",
1798 ret->name);
1799 xmlFree(fixed);
1800 } else if (fixed != NULL) {
1801 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
1802 ret->value = fixed;
1805 child = node->children;
1806 if (IS_SCHEMA(child, "annotation")) {
1807 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1808 child = child->next;
1810 if (IS_SCHEMA(child, "complexType")) {
1811 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
1812 child = child->next;
1813 } else if (IS_SCHEMA(child, "simpleType")) {
1814 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1815 child = child->next;
1817 while ((IS_SCHEMA(child, "unique")) ||
1818 (IS_SCHEMA(child, "key")) ||
1819 (IS_SCHEMA(child, "keyref"))) {
1820 TODO
1821 child = child->next;
1823 if (child != NULL) {
1824 xmlSchemaErrorContext(ctxt, schema, node, child);
1825 if ((ctxt != NULL) && (ctxt->error != NULL))
1826 ctxt->error(ctxt->userData,
1827 "element %s has unexpected content\n",
1828 name);
1831 ctxt->container = oldcontainer;
1832 xmlFree(name);
1833 return (ret);
1837 * xmlSchemaParseUnion:
1838 * @ctxt: a schema validation context
1839 * @schema: the schema being built
1840 * @node: a subtree containing XML Schema informations
1842 * parse a XML schema Union definition
1843 * *WARNING* this interface is highly subject to change
1845 * Returns -1 in case of error, 0 if the declaration is inproper and
1846 * 1 in case of success.
1848 static xmlSchemaTypePtr
1849 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1850 xmlNodePtr node)
1852 xmlSchemaTypePtr type, subtype, last = NULL;
1853 xmlNodePtr child = NULL;
1854 xmlChar name[30];
1856 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1857 return (NULL);
1860 snprintf((char *)name, 30, "union %d", ctxt->counter++ + 1);
1861 type = xmlSchemaAddType(ctxt, schema, name);
1862 if (type == NULL)
1863 return (NULL);
1864 type->node = node;
1865 type->type = XML_SCHEMA_TYPE_LIST;
1866 type->id = xmlGetProp(node, BAD_CAST "id");
1867 type->ref = xmlGetProp(node, BAD_CAST "memberTypes");
1869 child = node->children;
1870 if (IS_SCHEMA(child, "annotation")) {
1871 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1872 child = child->next;
1874 while (IS_SCHEMA(child, "simpleType")) {
1875 subtype = (xmlSchemaTypePtr)
1876 xmlSchemaParseSimpleType(ctxt, schema, child);
1877 if (subtype != NULL) {
1878 if (last == NULL) {
1879 type->subtypes = subtype;
1880 last = subtype;
1881 } else {
1882 last->next = subtype;
1883 last = subtype;
1885 last->next = NULL;
1887 child = child->next;
1889 if (child != NULL) {
1890 xmlSchemaErrorContext(ctxt, schema, node, child);
1891 if ((ctxt != NULL) && (ctxt->error != NULL))
1892 ctxt->error(ctxt->userData,
1893 "Union %s has unexpected content\n",
1894 type->name);
1896 return (type);
1900 * xmlSchemaParseList:
1901 * @ctxt: a schema validation context
1902 * @schema: the schema being built
1903 * @node: a subtree containing XML Schema informations
1905 * parse a XML schema List definition
1906 * *WARNING* this interface is highly subject to change
1908 * Returns -1 in case of error, 0 if the declaration is inproper and
1909 * 1 in case of success.
1911 static xmlSchemaTypePtr
1912 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1913 xmlNodePtr node)
1915 xmlSchemaTypePtr type, subtype;
1916 xmlNodePtr child = NULL;
1917 xmlChar name[30];
1919 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1920 return (NULL);
1922 snprintf((char *)name, 30, "list %d", ctxt->counter++ + 1);
1923 type = xmlSchemaAddType(ctxt, schema, name);
1924 if (type == NULL)
1925 return (NULL);
1926 type->node = node;
1927 type->type = XML_SCHEMA_TYPE_LIST;
1928 type->id = xmlGetProp(node, BAD_CAST "id");
1929 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
1931 child = node->children;
1932 if (IS_SCHEMA(child, "annotation")) {
1933 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1934 child = child->next;
1936 subtype = NULL;
1937 if (IS_SCHEMA(child, "simpleType")) {
1938 subtype = (xmlSchemaTypePtr)
1939 xmlSchemaParseSimpleType(ctxt, schema, child);
1940 child = child->next;
1941 type->subtypes = subtype;
1943 if (child != NULL) {
1944 xmlSchemaErrorContext(ctxt, schema, node, child);
1945 if ((ctxt != NULL) && (ctxt->error != NULL))
1946 ctxt->error(ctxt->userData,
1947 "List %s has unexpected content\n",
1948 type->name);
1950 return (type);
1953 * xmlSchemaParseSimpleType:
1954 * @ctxt: a schema validation context
1955 * @schema: the schema being built
1956 * @node: a subtree containing XML Schema informations
1958 * parse a XML schema Simple Type definition
1959 * *WARNING* this interface is highly subject to change
1961 * Returns -1 in case of error, 0 if the declaration is inproper and
1962 * 1 in case of success.
1964 static xmlSchemaTypePtr
1965 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1966 xmlNodePtr node)
1968 xmlSchemaTypePtr type, subtype;
1969 xmlNodePtr child = NULL;
1970 xmlChar *name;
1972 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1973 return (NULL);
1976 name = xmlGetProp(node, (const xmlChar *) "name");
1977 if (name == NULL) {
1978 char buf[100];
1980 snprintf(buf, 99, "simpletype%d", ctxt->counter++ + 1);
1981 name = xmlStrdup((xmlChar *) buf);
1983 if (name == NULL) {
1984 xmlSchemaErrorContext(ctxt, schema, node, child);
1985 if ((ctxt != NULL) && (ctxt->error != NULL))
1986 ctxt->error(ctxt->userData, "simpleType has no name\n");
1987 return (NULL);
1989 type = xmlSchemaAddType(ctxt, schema, name);
1990 xmlFree(name);
1991 if (type == NULL)
1992 return (NULL);
1993 type->node = node;
1994 type->type = XML_SCHEMA_TYPE_SIMPLE;
1995 type->id = xmlGetProp(node, BAD_CAST "id");
1997 child = node->children;
1998 if (IS_SCHEMA(child, "annotation")) {
1999 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2000 child = child->next;
2002 subtype = NULL;
2003 if (IS_SCHEMA(child, "restriction")) {
2004 subtype = (xmlSchemaTypePtr)
2005 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2006 child = child->next;
2007 } else if (IS_SCHEMA(child, "list")) {
2008 subtype = (xmlSchemaTypePtr)
2009 xmlSchemaParseList(ctxt, schema, child);
2010 child = child->next;
2011 } else if (IS_SCHEMA(child, "union")) {
2012 subtype = (xmlSchemaTypePtr)
2013 xmlSchemaParseUnion(ctxt, schema, child);
2014 child = child->next;
2016 type->subtypes = subtype;
2017 if (child != NULL) {
2018 xmlSchemaErrorContext(ctxt, schema, node, child);
2019 if ((ctxt != NULL) && (ctxt->error != NULL))
2020 ctxt->error(ctxt->userData,
2021 "SimpleType %s has unexpected content\n",
2022 type->name);
2025 return (type);
2030 * xmlSchemaParseGroup:
2031 * @ctxt: a schema validation context
2032 * @schema: the schema being built
2033 * @node: a subtree containing XML Schema informations
2035 * parse a XML schema Group definition
2036 * *WARNING* this interface is highly subject to change
2038 * Returns -1 in case of error, 0 if the declaration is inproper and
2039 * 1 in case of success.
2041 static xmlSchemaTypePtr
2042 xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2043 xmlNodePtr node)
2045 xmlSchemaTypePtr type, subtype;
2046 xmlNodePtr child = NULL;
2047 xmlChar *name, *ref = NULL, *refNs = NULL;
2049 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2050 return (NULL);
2053 name = xmlGetProp(node, (const xmlChar *) "name");
2054 if (name == NULL) {
2055 char buf[100];
2057 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2058 if (ref == NULL) {
2059 xmlSchemaErrorContext(ctxt, schema, node, child);
2060 if ((ctxt != NULL) && (ctxt->error != NULL))
2061 ctxt->error(ctxt->userData, "Group has no name nor ref\n");
2062 return (NULL);
2064 snprintf(buf, 99, "anongroup%d", ctxt->counter++ + 1);
2065 name = xmlStrdup((xmlChar *) buf);
2067 type = xmlSchemaAddType(ctxt, schema, name);
2068 if (type == NULL)
2069 return (NULL);
2070 type->node = node;
2071 type->type = XML_SCHEMA_TYPE_GROUP;
2072 type->id = xmlGetProp(node, BAD_CAST "id");
2073 type->ref = ref;
2074 type->refNs = refNs;
2075 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2076 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2078 child = node->children;
2079 if (IS_SCHEMA(child, "annotation")) {
2080 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2081 child = child->next;
2083 subtype = NULL;
2084 if (IS_SCHEMA(child, "all")) {
2085 subtype = (xmlSchemaTypePtr)
2086 xmlSchemaParseAll(ctxt, schema, child);
2087 child = child->next;
2088 } else if (IS_SCHEMA(child, "choice")) {
2089 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2090 child = child->next;
2091 } else if (IS_SCHEMA(child, "sequence")) {
2092 subtype = (xmlSchemaTypePtr)
2093 xmlSchemaParseSequence(ctxt, schema, child);
2094 child = child->next;
2096 if (subtype != NULL)
2097 type->subtypes = subtype;
2098 if (child != NULL) {
2099 xmlSchemaErrorContext(ctxt, schema, node, child);
2100 if ((ctxt != NULL) && (ctxt->error != NULL))
2101 ctxt->error(ctxt->userData,
2102 "Group %s has unexpected content\n",
2103 type->name);
2106 return (type);
2110 * xmlSchemaParseAll:
2111 * @ctxt: a schema validation context
2112 * @schema: the schema being built
2113 * @node: a subtree containing XML Schema informations
2115 * parse a XML schema All definition
2116 * *WARNING* this interface is highly subject to change
2118 * Returns -1 in case of error, 0 if the declaration is inproper and
2119 * 1 in case of success.
2121 static xmlSchemaTypePtr
2122 xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2123 xmlNodePtr node)
2125 xmlSchemaTypePtr type, subtype, last = NULL;
2126 xmlNodePtr child = NULL;
2127 xmlChar name[30];
2129 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2130 return (NULL);
2133 snprintf((char *)name, 30, "all%d", ctxt->counter++ + 1);
2134 type = xmlSchemaAddType(ctxt, schema, name);
2135 if (type == NULL)
2136 return (NULL);
2137 type->node = node;
2138 type->type = XML_SCHEMA_TYPE_ALL;
2139 type->id = xmlGetProp(node, BAD_CAST "id");
2140 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2141 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2143 child = node->children;
2144 if (IS_SCHEMA(child, "annotation")) {
2145 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2146 child = child->next;
2148 while (IS_SCHEMA(child, "element")) {
2149 subtype = (xmlSchemaTypePtr)
2150 xmlSchemaParseElement(ctxt, schema, child, 0);
2151 if (subtype != NULL) {
2152 if (last == NULL) {
2153 type->subtypes = subtype;
2154 last = subtype;
2155 } else {
2156 last->next = subtype;
2157 last = subtype;
2159 last->next = NULL;
2161 child = child->next;
2163 if (child != NULL) {
2164 xmlSchemaErrorContext(ctxt, schema, node, child);
2165 if ((ctxt != NULL) && (ctxt->error != NULL))
2166 ctxt->error(ctxt->userData,
2167 "All %s has unexpected content\n",
2168 type->name);
2171 return (type);
2175 * xmlSchemaParseImport:
2176 * @ctxt: a schema validation context
2177 * @schema: the schema being built
2178 * @node: a subtree containing XML Schema informations
2180 * parse a XML schema Import definition
2181 * *WARNING* this interface is highly subject to change
2183 * Returns -1 in case of error, 0 if the declaration is inproper and
2184 * 1 in case of success.
2186 static int
2187 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2188 xmlNodePtr node)
2190 xmlNodePtr child = NULL;
2191 xmlChar *namespace;
2192 xmlChar *schemaLocation;
2193 xmlChar *previous;
2194 xmlURIPtr check;
2196 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2197 return (-1);
2199 namespace = xmlGetProp(node, BAD_CAST "namespace");
2200 if (namespace != NULL) {
2201 check = xmlParseURI((const char *) namespace);
2202 if (check == NULL) {
2203 xmlSchemaErrorContext(ctxt, schema, node, child);
2204 if ((ctxt != NULL) && (ctxt->error != NULL))
2205 ctxt->error(ctxt->userData,
2206 "Import namespace attribute is not an URI: %s\n",
2207 namespace);
2208 xmlFree(namespace);
2209 return(-1);
2210 } else {
2211 xmlFreeURI(check);
2214 schemaLocation = xmlGetProp(node, BAD_CAST "schemaLocation");
2215 if (schemaLocation != NULL) {
2216 check = xmlParseURI((const char *) schemaLocation);
2217 if (check == NULL) {
2218 xmlSchemaErrorContext(ctxt, schema, node, child);
2219 if ((ctxt != NULL) && (ctxt->error != NULL))
2220 ctxt->error(ctxt->userData,
2221 "Import schemaLocation attribute is not an URI: %s\n",
2222 schemaLocation);
2223 if (namespace != NULL)
2224 xmlFree(namespace);
2225 xmlFree(schemaLocation);
2226 return(-1);
2227 } else {
2228 xmlFreeURI(check);
2231 if (schema->schemasImports == NULL) {
2232 schema->schemasImports = xmlHashCreate(10);
2233 if (schema->schemasImports == NULL) {
2234 xmlSchemaErrorContext(ctxt, schema, node, child);
2235 if ((ctxt != NULL) && (ctxt->error != NULL))
2236 ctxt->error(ctxt->userData,
2237 "Internal: failed to build import table\n");
2238 if (namespace != NULL)
2239 xmlFree(namespace);
2240 if (schemaLocation != NULL)
2241 xmlFree(schemaLocation);
2242 return(-1);
2245 if (namespace == NULL) {
2246 previous = xmlHashLookup(schema->schemasImports,
2247 XML_SCHEMAS_DEFAULT_NAMESPACE);
2248 if (schemaLocation != NULL) {
2249 if (previous != NULL) {
2250 if (!xmlStrEqual(schemaLocation, previous)) {
2251 xmlSchemaErrorContext(ctxt, schema, node, child);
2252 if ((ctxt != NULL) && (ctxt->error != NULL))
2253 ctxt->error(ctxt->userData,
2254 "Redefining import for default namespace with a different URI: %s\n",
2255 schemaLocation);
2257 } else {
2258 xmlHashAddEntry(schema->schemasImports,
2259 XML_SCHEMAS_DEFAULT_NAMESPACE, schemaLocation);
2262 } else {
2263 previous = xmlHashLookup(schema->schemasImports, namespace);
2264 if (schemaLocation != NULL) {
2265 if (previous != NULL) {
2266 if (!xmlStrEqual(schemaLocation, previous)) {
2267 xmlSchemaErrorContext(ctxt, schema, node, child);
2268 if ((ctxt != NULL) && (ctxt->error != NULL))
2269 ctxt->error(ctxt->userData,
2270 "Redefining import for namespace %s with a different URI: %s\n",
2271 namespace, schemaLocation);
2273 } else {
2274 xmlHashAddEntry(schema->schemasImports,
2275 namespace, schemaLocation);
2280 child = node->children;
2281 while (IS_SCHEMA(child, "annotation")) {
2283 * the annotations here are simply discarded ...
2285 child = child->next;
2287 if (child != NULL) {
2288 xmlSchemaErrorContext(ctxt, schema, node, child);
2289 if ((ctxt != NULL) && (ctxt->error != NULL))
2290 ctxt->error(ctxt->userData,
2291 "Import has unexpected content\n");
2292 return(-1);
2294 return(1);
2298 * xmlSchemaParseChoice:
2299 * @ctxt: a schema validation context
2300 * @schema: the schema being built
2301 * @node: a subtree containing XML Schema informations
2303 * parse a XML schema Choice definition
2304 * *WARNING* this interface is highly subject to change
2306 * Returns -1 in case of error, 0 if the declaration is inproper and
2307 * 1 in case of success.
2309 static xmlSchemaTypePtr
2310 xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2311 xmlNodePtr node)
2313 xmlSchemaTypePtr type, subtype, last = NULL;
2314 xmlNodePtr child = NULL;
2315 xmlChar name[30];
2317 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2318 return (NULL);
2321 snprintf((char *)name, 30, "choice %d", ctxt->counter++ + 1);
2322 type = xmlSchemaAddType(ctxt, schema, name);
2323 if (type == NULL)
2324 return (NULL);
2325 type->node = node;
2326 type->type = XML_SCHEMA_TYPE_CHOICE;
2327 type->id = xmlGetProp(node, BAD_CAST "id");
2328 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2329 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2331 child = node->children;
2332 if (IS_SCHEMA(child, "annotation")) {
2333 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2334 child = child->next;
2336 while ((IS_SCHEMA(child, "element")) ||
2337 (IS_SCHEMA(child, "group")) ||
2338 (IS_SCHEMA(child, "any")) ||
2339 (IS_SCHEMA(child, "choice")) ||
2340 (IS_SCHEMA(child, "sequence"))) {
2341 subtype = NULL;
2342 if (IS_SCHEMA(child, "element")) {
2343 subtype = (xmlSchemaTypePtr)
2344 xmlSchemaParseElement(ctxt, schema, child, 0);
2345 } else if (IS_SCHEMA(child, "group")) {
2346 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2347 } else if (IS_SCHEMA(child, "any")) {
2348 subtype = xmlSchemaParseAny(ctxt, schema, child);
2349 } else if (IS_SCHEMA(child, "sequence")) {
2350 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2351 } else if (IS_SCHEMA(child, "choice")) {
2352 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2354 if (subtype != NULL) {
2355 if (last == NULL) {
2356 type->subtypes = subtype;
2357 last = subtype;
2358 } else {
2359 last->next = subtype;
2360 last = subtype;
2362 last->next = NULL;
2364 child = child->next;
2366 if (child != NULL) {
2367 xmlSchemaErrorContext(ctxt, schema, node, child);
2368 if ((ctxt != NULL) && (ctxt->error != NULL))
2369 ctxt->error(ctxt->userData,
2370 "Choice %s has unexpected content\n",
2371 type->name);
2374 return (type);
2378 * xmlSchemaParseSequence:
2379 * @ctxt: a schema validation context
2380 * @schema: the schema being built
2381 * @node: a subtree containing XML Schema informations
2383 * parse a XML schema Sequence definition
2384 * *WARNING* this interface is highly subject to change
2386 * Returns -1 in case of error, 0 if the declaration is inproper and
2387 * 1 in case of success.
2389 static xmlSchemaTypePtr
2390 xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2391 xmlNodePtr node)
2393 xmlSchemaTypePtr type, subtype, last = NULL;
2394 xmlNodePtr child = NULL;
2395 xmlChar name[30];
2397 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2398 return (NULL);
2401 snprintf((char *)name, 30, "sequence %d", ctxt->counter++ + 1);
2402 type = xmlSchemaAddType(ctxt, schema, name);
2403 if (type == NULL)
2404 return (NULL);
2405 type->node = node;
2406 type->type = XML_SCHEMA_TYPE_SEQUENCE;
2407 type->id = xmlGetProp(node, BAD_CAST "id");
2408 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2409 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2411 child = node->children;
2412 if (IS_SCHEMA(child, "annotation")) {
2413 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2414 child = child->next;
2416 while ((IS_SCHEMA(child, "element")) ||
2417 (IS_SCHEMA(child, "group")) ||
2418 (IS_SCHEMA(child, "any")) ||
2419 (IS_SCHEMA(child, "choice")) ||
2420 (IS_SCHEMA(child, "sequence"))) {
2421 subtype = NULL;
2422 if (IS_SCHEMA(child, "element")) {
2423 subtype = (xmlSchemaTypePtr)
2424 xmlSchemaParseElement(ctxt, schema, child, 0);
2425 } else if (IS_SCHEMA(child, "group")) {
2426 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2427 } else if (IS_SCHEMA(child, "any")) {
2428 subtype = xmlSchemaParseAny(ctxt, schema, child);
2429 } else if (IS_SCHEMA(child, "choice")) {
2430 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2431 } else if (IS_SCHEMA(child, "sequence")) {
2432 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2434 if (subtype != NULL) {
2435 if (last == NULL) {
2436 type->subtypes = subtype;
2437 last = subtype;
2438 } else {
2439 last->next = subtype;
2440 last = subtype;
2442 last->next = NULL;
2444 child = child->next;
2446 if (child != NULL) {
2447 xmlSchemaErrorContext(ctxt, schema, node, child);
2448 if ((ctxt != NULL) && (ctxt->error != NULL))
2449 ctxt->error(ctxt->userData,
2450 "Sequence %s has unexpected content\n",
2451 type->name);
2454 return (type);
2458 * xmlSchemaParseRestriction:
2459 * @ctxt: a schema validation context
2460 * @schema: the schema being built
2461 * @node: a subtree containing XML Schema informations
2462 * @simple: is that part of a simple type.
2464 * parse a XML schema Restriction definition
2465 * *WARNING* this interface is highly subject to change
2467 * Returns the type definition or NULL in case of error
2469 static xmlSchemaTypePtr
2470 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2471 xmlNodePtr node, int simple)
2473 xmlSchemaTypePtr type, subtype;
2474 xmlSchemaFacetPtr facet, lastfacet = NULL;
2475 xmlNodePtr child = NULL;
2476 xmlChar name[30];
2477 xmlChar *oldcontainer;
2479 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2480 return (NULL);
2482 oldcontainer = ctxt->container;
2484 snprintf((char *)name, 30, "restriction %d", ctxt->counter++ + 1);
2485 type = xmlSchemaAddType(ctxt, schema, name);
2486 if (type == NULL)
2487 return (NULL);
2488 type->node = node;
2489 type->type = XML_SCHEMA_TYPE_RESTRICTION;
2490 type->id = xmlGetProp(node, BAD_CAST "id");
2491 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2492 if ((!simple) && (type->base == NULL)) {
2493 xmlSchemaErrorContext(ctxt, schema, node, child);
2494 if ((ctxt != NULL) && (ctxt->error != NULL))
2495 ctxt->error(ctxt->userData,
2496 "Restriction %s has no base\n",
2497 type->name);
2499 ctxt->container = name;
2501 child = node->children;
2502 if (IS_SCHEMA(child, "annotation")) {
2503 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2504 child = child->next;
2506 subtype = NULL;
2508 if (IS_SCHEMA(child, "all")) {
2509 subtype = (xmlSchemaTypePtr)
2510 xmlSchemaParseAll(ctxt, schema, child);
2511 child = child->next;
2512 type->subtypes = subtype;
2513 } else if (IS_SCHEMA(child, "choice")) {
2514 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2515 child = child->next;
2516 type->subtypes = subtype;
2517 } else if (IS_SCHEMA(child, "sequence")) {
2518 subtype = (xmlSchemaTypePtr)
2519 xmlSchemaParseSequence(ctxt, schema, child);
2520 child = child->next;
2521 type->subtypes = subtype;
2522 } else if (IS_SCHEMA(child, "group")) {
2523 subtype = (xmlSchemaTypePtr)
2524 xmlSchemaParseGroup(ctxt, schema, child);
2525 child = child->next;
2526 type->subtypes = subtype;
2527 } else {
2528 if (IS_SCHEMA(child, "simpleType")) {
2529 subtype = (xmlSchemaTypePtr)
2530 xmlSchemaParseSimpleType(ctxt, schema, child);
2531 child = child->next;
2532 type->baseType = subtype;
2535 * Facets
2537 while ((IS_SCHEMA(child, "minInclusive")) ||
2538 (IS_SCHEMA(child, "minExclusive")) ||
2539 (IS_SCHEMA(child, "maxInclusive")) ||
2540 (IS_SCHEMA(child, "maxExclusive")) ||
2541 (IS_SCHEMA(child, "totalDigits")) ||
2542 (IS_SCHEMA(child, "fractionDigits")) ||
2543 (IS_SCHEMA(child, "pattern")) ||
2544 (IS_SCHEMA(child, "enumeration")) ||
2545 (IS_SCHEMA(child, "whiteSpace")) ||
2546 (IS_SCHEMA(child, "length")) ||
2547 (IS_SCHEMA(child, "maxLength")) ||
2548 (IS_SCHEMA(child, "minLength"))) {
2549 facet = xmlSchemaParseFacet(ctxt, schema, child);
2550 if (facet != NULL) {
2551 if (lastfacet == NULL) {
2552 type->facets = facet;
2553 lastfacet = facet;
2554 } else {
2555 lastfacet->next = facet;
2556 lastfacet = facet;
2558 lastfacet->next = NULL;
2560 child = child->next;
2563 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2564 if (child != NULL) {
2565 xmlSchemaErrorContext(ctxt, schema, node, child);
2566 if ((ctxt != NULL) && (ctxt->error != NULL))
2567 ctxt->error(ctxt->userData,
2568 "Restriction %s has unexpected content\n",
2569 type->name);
2571 ctxt->container = oldcontainer;
2572 return (type);
2576 * xmlSchemaParseExtension:
2577 * @ctxt: a schema validation context
2578 * @schema: the schema being built
2579 * @node: a subtree containing XML Schema informations
2581 * parse a XML schema Extension definition
2582 * *WARNING* this interface is highly subject to change
2584 * Returns the type definition or NULL in case of error
2586 static xmlSchemaTypePtr
2587 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2588 xmlNodePtr node)
2590 xmlSchemaTypePtr type, subtype;
2591 xmlNodePtr child = NULL;
2592 xmlChar name[30];
2593 xmlChar *oldcontainer;
2595 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2596 return (NULL);
2598 oldcontainer = ctxt->container;
2600 snprintf((char *)name, 30, "extension %d", ctxt->counter++ + 1);
2601 type = xmlSchemaAddType(ctxt, schema, name);
2602 if (type == NULL)
2603 return (NULL);
2604 type->node = node;
2605 type->type = XML_SCHEMA_TYPE_EXTENSION;
2606 type->id = xmlGetProp(node, BAD_CAST "id");
2607 ctxt->container = name;
2609 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2610 if (type->base == NULL) {
2611 xmlSchemaErrorContext(ctxt, schema, node, child);
2612 if ((ctxt != NULL) && (ctxt->error != NULL))
2613 ctxt->error(ctxt->userData,
2614 "Extension %s has no base\n",
2615 type->name);
2617 child = node->children;
2618 if (IS_SCHEMA(child, "annotation")) {
2619 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2620 child = child->next;
2622 subtype = NULL;
2624 if (IS_SCHEMA(child, "all")) {
2625 subtype = xmlSchemaParseAll(ctxt, schema, child);
2626 child = child->next;
2627 } else if (IS_SCHEMA(child, "choice")) {
2628 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2629 child = child->next;
2630 } else if (IS_SCHEMA(child, "sequence")) {
2631 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2632 child = child->next;
2633 } else if (IS_SCHEMA(child, "group")) {
2634 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2635 child = child->next;
2637 if (subtype != NULL)
2638 type->subtypes = subtype;
2639 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2640 if (child != NULL) {
2641 xmlSchemaErrorContext(ctxt, schema, node, child);
2642 if ((ctxt != NULL) && (ctxt->error != NULL))
2643 ctxt->error(ctxt->userData,
2644 "Extension %s has unexpected content\n",
2645 type->name);
2647 ctxt->container = oldcontainer;
2648 return (type);
2652 * xmlSchemaParseSimpleContent:
2653 * @ctxt: a schema validation context
2654 * @schema: the schema being built
2655 * @node: a subtree containing XML Schema informations
2657 * parse a XML schema SimpleContent definition
2658 * *WARNING* this interface is highly subject to change
2660 * Returns the type definition or NULL in case of error
2662 static xmlSchemaTypePtr
2663 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2664 xmlNodePtr node)
2666 xmlSchemaTypePtr type, subtype;
2667 xmlNodePtr child = NULL;
2668 xmlChar name[30];
2670 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2671 return (NULL);
2674 snprintf((char *)name, 30, "complexContent %d", ctxt->counter++ + 1);
2675 type = xmlSchemaAddType(ctxt, schema, name);
2676 if (type == NULL)
2677 return (NULL);
2678 type->node = node;
2679 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
2680 type->id = xmlGetProp(node, BAD_CAST "id");
2682 child = node->children;
2683 if (IS_SCHEMA(child, "annotation")) {
2684 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2685 child = child->next;
2687 subtype = NULL;
2688 if (IS_SCHEMA(child, "restriction")) {
2689 subtype = (xmlSchemaTypePtr)
2690 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2691 child = child->next;
2692 } else if (IS_SCHEMA(child, "extension")) {
2693 subtype = (xmlSchemaTypePtr)
2694 xmlSchemaParseExtension(ctxt, schema, child);
2695 child = child->next;
2697 type->subtypes = subtype;
2698 if (child != NULL) {
2699 xmlSchemaErrorContext(ctxt, schema, node, child);
2700 if ((ctxt != NULL) && (ctxt->error != NULL))
2701 ctxt->error(ctxt->userData,
2702 "SimpleContent %s has unexpected content\n",
2703 type->name);
2705 return (type);
2709 * xmlSchemaParseComplexContent:
2710 * @ctxt: a schema validation context
2711 * @schema: the schema being built
2712 * @node: a subtree containing XML Schema informations
2714 * parse a XML schema ComplexContent definition
2715 * *WARNING* this interface is highly subject to change
2717 * Returns the type definition or NULL in case of error
2719 static xmlSchemaTypePtr
2720 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2721 xmlNodePtr node)
2723 xmlSchemaTypePtr type, subtype;
2724 xmlNodePtr child = NULL;
2725 xmlChar name[30];
2727 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2728 return (NULL);
2731 snprintf((char *)name, 30, "complexContent %d", ctxt->counter++ + 1);
2732 type = xmlSchemaAddType(ctxt, schema, name);
2733 if (type == NULL)
2734 return (NULL);
2735 type->node = node;
2736 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
2737 type->id = xmlGetProp(node, BAD_CAST "id");
2739 child = node->children;
2740 if (IS_SCHEMA(child, "annotation")) {
2741 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2742 child = child->next;
2744 subtype = NULL;
2745 if (IS_SCHEMA(child, "restriction")) {
2746 subtype = (xmlSchemaTypePtr)
2747 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2748 child = child->next;
2749 } else if (IS_SCHEMA(child, "extension")) {
2750 subtype = (xmlSchemaTypePtr)
2751 xmlSchemaParseExtension(ctxt, schema, child);
2752 child = child->next;
2754 type->subtypes = subtype;
2755 if (child != NULL) {
2756 xmlSchemaErrorContext(ctxt, schema, node, child);
2757 if ((ctxt != NULL) && (ctxt->error != NULL))
2758 ctxt->error(ctxt->userData,
2759 "ComplexContent %s has unexpected content\n",
2760 type->name);
2762 return (type);
2766 * xmlSchemaParseComplexType:
2767 * @ctxt: a schema validation context
2768 * @schema: the schema being built
2769 * @node: a subtree containing XML Schema informations
2771 * parse a XML schema Complex Type definition
2772 * *WARNING* this interface is highly subject to change
2774 * Returns the type definition or NULL in case of error
2776 static xmlSchemaTypePtr
2777 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2778 xmlNodePtr node)
2780 xmlSchemaTypePtr type, subtype;
2781 xmlNodePtr child = NULL;
2782 xmlChar *name;
2783 xmlChar *oldcontainer;
2785 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2786 return (NULL);
2788 oldcontainer = ctxt->container;
2789 name = xmlGetProp(node, (const xmlChar *) "name");
2790 if (name == NULL) {
2791 char buf[100];
2793 snprintf(buf, 99, "anontype%d", ctxt->counter++ + 1);
2794 name = xmlStrdup((xmlChar *) buf);
2796 if (name == NULL) {
2797 xmlSchemaErrorContext(ctxt, schema, node, child);
2798 if ((ctxt != NULL) && (ctxt->error != NULL))
2799 ctxt->error(ctxt->userData, "complexType has no name\n");
2800 return (NULL);
2802 type = xmlSchemaAddType(ctxt, schema, name);
2803 if (type == NULL) {
2804 xmlFree(name);
2805 return (NULL);
2807 type->node = node;
2808 type->type = XML_SCHEMA_TYPE_COMPLEX;
2809 type->id = xmlGetProp(node, BAD_CAST "id");
2810 ctxt->container = name;
2812 child = node->children;
2813 if (IS_SCHEMA(child, "annotation")) {
2814 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2815 child = child->next;
2817 if (IS_SCHEMA(child, "simpleContent")) {
2818 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
2819 child = child->next;
2820 } else if (IS_SCHEMA(child, "complexContent")) {
2821 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
2822 child = child->next;
2823 } else {
2824 subtype = NULL;
2826 if (IS_SCHEMA(child, "all")) {
2827 subtype = xmlSchemaParseAll(ctxt, schema, child);
2828 child = child->next;
2829 } else if (IS_SCHEMA(child, "choice")) {
2830 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2831 child = child->next;
2832 } else if (IS_SCHEMA(child, "sequence")) {
2833 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2834 child = child->next;
2835 } else if (IS_SCHEMA(child, "group")) {
2836 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2837 child = child->next;
2839 if (subtype != NULL)
2840 type->subtypes = subtype;
2841 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2843 if (child != NULL) {
2844 xmlSchemaErrorContext(ctxt, schema, node, child);
2845 if ((ctxt != NULL) && (ctxt->error != NULL))
2846 ctxt->error(ctxt->userData,
2847 "ComplexType %s has unexpected content\n",
2848 type->name);
2850 ctxt->container = oldcontainer;
2851 xmlFree(name);
2852 return (type);
2857 * xmlSchemaParseSchema:
2858 * @ctxt: a schema validation context
2859 * @node: a subtree containing XML Schema informations
2861 * parse a XML schema definition from a node set
2862 * *WARNING* this interface is highly subject to change
2864 * Returns the internal XML Schema structure built from the resource or
2865 * NULL in case of error
2867 static xmlSchemaPtr
2868 xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2870 xmlSchemaPtr schema = NULL;
2871 xmlSchemaAnnotPtr annot;
2872 xmlNodePtr child = NULL;
2873 xmlChar *val;
2875 if ((ctxt == NULL) || (node == NULL))
2876 return (NULL);
2878 if (IS_SCHEMA(node, "schema")) {
2879 schema = xmlSchemaNewSchema(ctxt);
2880 if (schema == NULL)
2881 return(NULL);
2882 schema->targetNamespace = xmlGetProp(node, BAD_CAST "targetNamespace");
2883 schema->id = xmlGetProp(node, BAD_CAST "id");
2884 schema->version = xmlGetProp(node, BAD_CAST "version");
2885 val = xmlGetProp(node, BAD_CAST "elementFormDefault");
2886 if (val != NULL) {
2887 if (xmlStrEqual(val, BAD_CAST "qualified"))
2888 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
2889 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
2890 xmlSchemaErrorContext(ctxt, schema, node, child);
2891 if ((ctxt != NULL) && (ctxt->error != NULL)) {
2892 ctxt->error(ctxt->userData,
2893 "Invalid value %s for elementFormDefault\n",
2894 val);
2897 xmlFree(val);
2899 val = xmlGetProp(node, BAD_CAST "attributeFormDefault");
2900 if (val != NULL) {
2901 if (xmlStrEqual(val, BAD_CAST "qualified"))
2902 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
2903 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
2904 xmlSchemaErrorContext(ctxt, schema, node, child);
2905 if ((ctxt != NULL) && (ctxt->error != NULL)) {
2906 ctxt->error(ctxt->userData,
2907 "Invalid value %s for elementFormDefault\n",
2908 val);
2911 xmlFree(val);
2914 child = node->children;
2915 while ((IS_SCHEMA(child, "include")) ||
2916 (IS_SCHEMA(child, "import")) ||
2917 (IS_SCHEMA(child, "redefine")) ||
2918 (IS_SCHEMA(child, "annotation"))) {
2919 if (IS_SCHEMA(child, "annotation")) {
2920 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2921 if (schema->annot == NULL)
2922 schema->annot = annot;
2923 else
2924 xmlSchemaFreeAnnot(annot);
2925 } else if (IS_SCHEMA(child, "include")) {
2926 TODO
2927 } else if (IS_SCHEMA(child, "import")) {
2928 xmlSchemaParseImport(ctxt, schema, child);
2929 } else if (IS_SCHEMA(child, "redefine")) {
2930 TODO
2932 child = child->next;
2934 while (child != NULL) {
2935 if (IS_SCHEMA(child, "complexType")) {
2936 xmlSchemaParseComplexType(ctxt, schema, child);
2937 child = child->next;
2938 } else if (IS_SCHEMA(child, "simpleType")) {
2939 xmlSchemaParseSimpleType(ctxt, schema, child);
2940 child = child->next;
2941 } else if (IS_SCHEMA(child, "element")) {
2942 xmlSchemaParseElement(ctxt, schema, child, 1);
2943 child = child->next;
2944 } else if (IS_SCHEMA(child, "attribute")) {
2945 xmlSchemaParseAttribute(ctxt, schema, child);
2946 child = child->next;
2947 } else if (IS_SCHEMA(child, "attributeGroup")) {
2948 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2949 child = child->next;
2950 } else if (IS_SCHEMA(child, "group")) {
2951 xmlSchemaParseGroup(ctxt, schema, child);
2952 child = child->next;
2953 } else if (IS_SCHEMA(child, "notation")) {
2954 xmlSchemaParseNotation(ctxt, schema, child);
2955 child = child->next;
2956 } else {
2957 xmlSchemaErrorContext(ctxt, schema, node, child);
2958 if ((ctxt != NULL) && (ctxt->error != NULL))
2959 ctxt->error(ctxt->userData,
2960 "Schemas: unexpected element %s here \n",
2961 child->name);
2962 child = child->next;
2964 while (IS_SCHEMA(child, "annotation")) {
2965 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2966 if (schema->annot == NULL)
2967 schema->annot = annot;
2968 else
2969 xmlSchemaFreeAnnot(annot);
2970 child = child->next;
2974 #ifdef DEBUG
2975 if (schema == NULL)
2976 xmlGenericError(xmlGenericErrorContext,
2977 "xmlSchemaParse() failed\n");
2978 #endif
2980 return (schema);
2983 /************************************************************************
2985 * Validating using Schemas *
2987 ************************************************************************/
2989 /************************************************************************
2991 * Reading/Writing Schemas *
2993 ************************************************************************/
2996 * xmlSchemaNewParserCtxt:
2997 * @URL: the location of the schema
2999 * Create an XML Schemas parse context for that file/resource expected
3000 * to contain an XML Schemas file.
3002 * Returns the parser context or NULL in case of error
3004 xmlSchemaParserCtxtPtr
3005 xmlSchemaNewParserCtxt(const char *URL) {
3006 xmlSchemaParserCtxtPtr ret;
3008 if (URL == NULL)
3009 return(NULL);
3011 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3012 if (ret == NULL) {
3013 xmlGenericError(xmlGenericErrorContext,
3014 "Failed to allocate new schama parser context for %s\n", URL);
3015 return (NULL);
3017 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3018 ret->URL = xmlStrdup((const xmlChar *)URL);
3019 return (ret);
3023 * xmlSchemaNewMemParserCtxt:
3024 * @buffer: a pointer to a char array containing the schemas
3025 * @size: the size of the array
3027 * Create an XML Schemas parse context for that memory buffer expected
3028 * to contain an XML Schemas file.
3030 * Returns the parser context or NULL in case of error
3032 xmlSchemaParserCtxtPtr
3033 xmlSchemaNewMemParserCtxt(const char *buffer, int size) {
3034 xmlSchemaParserCtxtPtr ret;
3036 if ((buffer == NULL) || (size <= 0))
3037 return(NULL);
3039 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3040 if (ret == NULL) {
3041 xmlGenericError(xmlGenericErrorContext,
3042 "Failed to allocate new schama parser context\n");
3043 return (NULL);
3045 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3046 ret->buffer = buffer;
3047 ret->size = size;
3048 return (ret);
3052 * xmlSchemaFreeParserCtxt:
3053 * @ctxt: the schema parser context
3055 * Free the resources associated to the schema parser context
3057 void
3058 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) {
3059 if (ctxt == NULL)
3060 return;
3061 if (ctxt->URL != NULL)
3062 xmlFree(ctxt->URL);
3063 if (ctxt->doc != NULL)
3064 xmlFreeDoc(ctxt->doc);
3065 xmlFree(ctxt);
3068 /************************************************************************
3070 * Building the content models *
3072 ************************************************************************/
3074 * xmlSchemaBuildAContentModel:
3075 * @type: the schema type definition
3076 * @ctxt: the schema parser context
3077 * @name: the element name whose content is being built
3079 * Generate the automata sequence needed for that type
3081 static void
3082 xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
3083 xmlSchemaParserCtxtPtr ctxt,
3084 const xmlChar *name) {
3085 if (type == NULL) {
3086 xmlGenericError(xmlGenericErrorContext,
3087 "Found unexpected type = NULL in %s content model\n",
3088 name);
3089 return;
3091 switch (type->type) {
3092 case XML_SCHEMA_TYPE_ANY:
3093 /* TODO : handle the namespace too */
3094 /* TODO : make that a specific transition type */
3095 TODO
3096 ctxt->state = xmlAutomataNewTransition(ctxt->am, ctxt->state,
3097 NULL, BAD_CAST "*", NULL);
3098 break;
3099 case XML_SCHEMA_TYPE_ELEMENT: {
3100 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3101 /* TODO : handle the namespace too */
3102 xmlAutomataStatePtr oldstate = ctxt->state;
3103 if (elem->maxOccurs >= UNBOUNDED) {
3104 if (elem->minOccurs > 1) {
3105 xmlAutomataStatePtr tmp;
3106 int counter;
3108 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3109 oldstate, NULL);
3110 oldstate = ctxt->state;
3112 counter = xmlAutomataNewCounter(ctxt->am,
3113 elem->minOccurs - 1, UNBOUNDED);
3115 if (elem->refDecl != NULL) {
3116 xmlSchemaBuildAContentModel(
3117 (xmlSchemaTypePtr) elem->refDecl,
3118 ctxt, elem->refDecl->name);
3119 } else {
3120 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3121 ctxt->state, NULL, elem->name, type);
3123 tmp = ctxt->state;
3124 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3125 counter);
3126 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3127 NULL, counter);
3129 } else {
3130 if (elem->refDecl != NULL) {
3131 xmlSchemaBuildAContentModel(
3132 (xmlSchemaTypePtr) elem->refDecl,
3133 ctxt, elem->refDecl->name);
3134 } else {
3135 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3136 ctxt->state, NULL, elem->name, type);
3138 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
3139 if (elem->minOccurs == 0) {
3140 /* basically an elem* */
3141 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3144 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3145 xmlAutomataStatePtr tmp;
3146 int counter;
3148 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3149 oldstate, NULL);
3150 oldstate = ctxt->state;
3152 counter = xmlAutomataNewCounter(ctxt->am,
3153 elem->minOccurs - 1, elem->maxOccurs - 1);
3155 if (elem->refDecl != NULL) {
3156 xmlSchemaBuildAContentModel(
3157 (xmlSchemaTypePtr) elem->refDecl,
3158 ctxt, elem->refDecl->name);
3159 } else {
3160 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3161 ctxt->state, NULL, elem->name, type);
3163 tmp = ctxt->state;
3164 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3165 counter);
3166 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3167 NULL, counter);
3168 if (elem->minOccurs == 0) {
3169 /* basically an elem? */
3170 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3173 } else {
3174 if (elem->refDecl != NULL) {
3175 xmlSchemaBuildAContentModel(
3176 (xmlSchemaTypePtr) elem->refDecl,
3177 ctxt, elem->refDecl->name);
3178 } else {
3179 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3180 ctxt->state, NULL, elem->name, type);
3182 if (elem->minOccurs == 0) {
3183 /* basically an elem? */
3184 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3187 break;
3189 case XML_SCHEMA_TYPE_SEQUENCE: {
3190 xmlSchemaTypePtr subtypes;
3193 * If max and min occurances are default (1) then
3194 * simply iterate over the subtypes
3196 if ((type->minOccurs == 1 ) && (type->maxOccurs == 1)) {
3197 subtypes = type->subtypes;
3198 while (subtypes != NULL) {
3199 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3200 subtypes = subtypes->next;
3202 } else {
3203 xmlAutomataStatePtr oldstate = ctxt->state;
3204 if (type->maxOccurs >= UNBOUNDED) {
3205 if (type->minOccurs > 1) {
3206 xmlAutomataStatePtr tmp;
3207 int counter;
3209 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3210 oldstate, NULL);
3211 oldstate = ctxt->state;
3213 counter = xmlAutomataNewCounter(ctxt->am,
3214 type->minOccurs - 1, UNBOUNDED);
3216 subtypes = type->subtypes;
3217 while (subtypes != NULL) {
3218 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3219 subtypes = subtypes->next;
3221 tmp = ctxt->state;
3222 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3223 counter);
3224 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3225 NULL, counter);
3227 } else {
3228 subtypes = type->subtypes;
3229 while (subtypes != NULL) {
3230 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3231 subtypes = subtypes->next;
3233 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
3234 if (type->minOccurs == 0) {
3235 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3236 ctxt->state);
3239 } else if ((type->maxOccurs > 1) || (type->minOccurs > 1)) {
3240 xmlAutomataStatePtr tmp;
3241 int counter;
3243 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3244 oldstate, NULL);
3245 oldstate = ctxt->state;
3247 counter = xmlAutomataNewCounter(ctxt->am,
3248 type->minOccurs - 1, type->maxOccurs - 1);
3250 subtypes = type->subtypes;
3251 while (subtypes != NULL) {
3252 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3253 subtypes = subtypes->next;
3255 tmp = ctxt->state;
3256 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3257 counter);
3258 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3259 NULL, counter);
3260 if (type->minOccurs == 0) {
3261 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3264 } else {
3265 subtypes = type->subtypes;
3266 while (subtypes != NULL) {
3267 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3268 subtypes = subtypes->next;
3270 if (type->minOccurs == 0) {
3271 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3275 break;
3277 case XML_SCHEMA_TYPE_CHOICE: {
3278 xmlSchemaTypePtr subtypes;
3279 xmlAutomataStatePtr start, end;
3281 start = ctxt->state;
3282 end = xmlAutomataNewState(ctxt->am);
3285 * iterate over the subtypes and remerge the end with an
3286 * epsilon transition
3288 if (type->maxOccurs == 1) {
3289 subtypes = type->subtypes;
3290 while (subtypes != NULL) {
3291 ctxt->state = start;
3292 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3293 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
3294 subtypes = subtypes->next;
3296 } else {
3297 int counter;
3298 xmlAutomataStatePtr hop;
3299 int maxOccurs = type->maxOccurs == UNBOUNDED ?
3300 UNBOUNDED : type->maxOccurs - 1;
3301 int minOccurs = type->minOccurs < 1 ? 0 : type->minOccurs - 1;
3304 * use a counter to keep track of the number of transtions
3305 * which went through the choice.
3307 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
3308 hop = xmlAutomataNewState(ctxt->am);
3310 subtypes = type->subtypes;
3311 while (subtypes != NULL) {
3312 ctxt->state = start;
3313 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3314 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
3315 subtypes = subtypes->next;
3317 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
3318 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
3320 if (type->minOccurs == 0) {
3321 xmlAutomataNewEpsilon(ctxt->am, start, end);
3323 ctxt->state = end;
3324 break;
3326 case XML_SCHEMA_TYPE_ALL: {
3327 xmlAutomataStatePtr start;
3328 xmlSchemaTypePtr subtypes;
3329 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3330 int lax;
3332 subtypes = type->subtypes;
3333 if (subtypes == NULL)
3334 break;
3335 start = ctxt->state;
3336 while (subtypes != NULL) {
3337 ctxt->state = start;
3338 elem = (xmlSchemaElementPtr) subtypes;
3340 /* TODO : handle the namespace too */
3341 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state, ctxt->state,
3342 elem->name, elem->minOccurs, elem->maxOccurs,
3343 subtypes);
3344 subtypes = subtypes->next;
3346 lax = type->minOccurs == 0;
3347 ctxt->state = xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
3348 lax);
3349 break;
3351 case XML_SCHEMA_TYPE_RESTRICTION:
3352 if (type->subtypes != NULL)
3353 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3354 break;
3355 case XML_SCHEMA_TYPE_EXTENSION:
3356 if (type->baseType != NULL) {
3357 xmlSchemaTypePtr subtypes;
3359 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
3360 subtypes = type->subtypes;
3361 while (subtypes != NULL) {
3362 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3363 subtypes = subtypes->next;
3365 } else if (type->subtypes != NULL)
3366 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3367 break;
3368 case XML_SCHEMA_TYPE_GROUP:
3369 case XML_SCHEMA_TYPE_COMPLEX:
3370 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
3371 if (type->subtypes != NULL)
3372 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3373 break;
3374 default:
3375 xmlGenericError(xmlGenericErrorContext,
3376 "Found unexpected type %d in %s content model\n",
3377 type->type, name);
3378 return;
3382 * xmlSchemaBuildContentModel:
3383 * @typeDecl: the schema type definition
3384 * @ctxt: the schema parser context
3386 * Fixes the content model of the element.
3388 static void
3389 xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
3390 xmlSchemaParserCtxtPtr ctxt,
3391 const xmlChar *name) {
3392 xmlAutomataStatePtr start;
3394 if (elem->contModel != NULL)
3395 return;
3396 if (elem->subtypes == NULL) {
3397 elem->contentType = XML_SCHEMA_CONTENT_ANY;
3398 return;
3400 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
3401 return;
3402 if (elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC)
3403 return;
3405 #ifdef DEBUG_CONTENT
3406 xmlGenericError(xmlGenericErrorContext,
3407 "Building content model for %s\n", name);
3408 #endif
3410 ctxt->am = xmlNewAutomata();
3411 if (ctxt->am == NULL) {
3412 xmlGenericError(xmlGenericErrorContext,
3413 "Cannot create automata for elem %s\n", name);
3414 return;
3416 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3417 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3418 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
3419 elem->contModel = xmlAutomataCompile(ctxt->am);
3420 if (!xmlAutomataIsDeterminist(ctxt->am)) {
3421 xmlGenericError(xmlGenericErrorContext,
3422 "Content model of %s is not determinist:\n", name);
3423 ctxt->err = XML_SCHEMAS_ERR_NOTDETERMINIST;
3424 ctxt->state = NULL;
3425 } else {
3426 #ifdef DEBUG_CONTENT_REGEXP
3427 xmlGenericError(xmlGenericErrorContext,
3428 "Content model of %s:\n", name);
3429 xmlRegexpPrint(stderr, elem->contModel);
3430 #endif
3431 ctxt->state = NULL;
3433 xmlFreeAutomata(ctxt->am);
3434 ctxt->am = NULL;
3438 * xmlSchemaRefFixupCallback:
3439 * @elem: the schema element context
3440 * @ctxt: the schema parser context
3442 * Free the resources associated to the schema parser context
3444 static void
3445 xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
3446 xmlSchemaParserCtxtPtr ctxt,
3447 const xmlChar *name,
3448 const xmlChar *context ATTRIBUTE_UNUSED,
3449 const xmlChar *namespace ATTRIBUTE_UNUSED)
3451 if ((ctxt == NULL) || (elem == NULL))
3452 return;
3453 if (elem->ref != NULL) {
3454 xmlSchemaElementPtr elemDecl;
3456 if (elem->subtypes != NULL) {
3457 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3458 if ((ctxt != NULL) && (ctxt->error != NULL))
3459 ctxt->error(ctxt->userData,
3460 "Schemas: element %s have both ref and subtype\n",
3461 name);
3462 return;
3464 elemDecl = xmlHashLookup2(ctxt->schema->elemDecl,
3465 elem->ref, elem->refNs);
3467 if (elemDecl == NULL) {
3468 if ((ctxt != NULL) && (ctxt->error != NULL))
3469 ctxt->error(ctxt->userData,
3470 "Schemas: element %s ref to %s not found\n",
3471 name, elem->ref);
3472 return;
3474 elem->refDecl = elemDecl;
3475 } else if (elem->namedType != NULL) {
3476 xmlSchemaTypePtr typeDecl;
3478 if (elem->subtypes != NULL) {
3479 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3480 if ((ctxt != NULL) && (ctxt->error != NULL))
3481 ctxt->error(ctxt->userData,
3482 "Schemas: element %s have both type and subtype\n",
3483 name);
3484 return;
3486 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3487 elem->namedTypeNs);
3489 if (typeDecl == NULL) {
3490 if ((ctxt != NULL) && (ctxt->error != NULL))
3491 ctxt->error(ctxt->userData,
3492 "Schemas: element %s type %s not found\n",
3493 name, elem->namedType);
3494 return;
3496 elem->subtypes = typeDecl;
3501 * xmlSchemaTypeFixup:
3502 * @typeDecl: the schema type definition
3503 * @ctxt: the schema parser context
3505 * Fixes the content model of the type.
3507 static void
3508 xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
3509 xmlSchemaParserCtxtPtr ctxt,
3510 const xmlChar *name)
3512 if (name == NULL)
3513 name = typeDecl->name;
3514 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
3515 switch (typeDecl->type) {
3516 case XML_SCHEMA_TYPE_SIMPLE_CONTENT: {
3517 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3518 typeDecl->contentType = typeDecl->subtypes->contentType;
3519 break;
3521 case XML_SCHEMA_TYPE_RESTRICTION: {
3522 if (typeDecl->subtypes != NULL)
3523 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3525 if (typeDecl->base != NULL) {
3526 xmlSchemaTypePtr baseType;
3528 baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3529 typeDecl->baseNs);
3530 if (baseType == NULL) {
3531 if ((ctxt != NULL) && (ctxt->error != NULL))
3532 ctxt->error(ctxt->userData,
3533 "Schemas: type %s base type %s not found\n",
3534 name, typeDecl->base);
3536 typeDecl->baseType = baseType;
3538 if (typeDecl->subtypes == NULL)
3539 /* 1.1.1 */
3540 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3541 else if ((typeDecl->subtypes->subtypes == NULL) &&
3542 ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3543 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3544 /* 1.1.2 */
3545 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3546 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3547 (typeDecl->subtypes->subtypes == NULL))
3548 /* 1.1.3 */
3549 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3550 else {
3551 /* 1.2 and 2.X are applied at the other layer */
3552 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3554 break;
3556 case XML_SCHEMA_TYPE_EXTENSION: {
3557 xmlSchemaContentType explicitContentType;
3558 xmlSchemaTypePtr base;
3560 if (typeDecl->base != NULL) {
3561 xmlSchemaTypePtr baseType;
3563 baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3564 typeDecl->baseNs);
3565 if (baseType == NULL) {
3566 if ((ctxt != NULL) && (ctxt->error != NULL))
3567 ctxt->error(ctxt->userData,
3568 "Schemas: type %s base type %s not found\n",
3569 name, typeDecl->base);
3571 typeDecl->baseType = baseType;
3573 if (typeDecl->subtypes != NULL)
3574 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3576 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
3577 if (typeDecl->subtypes == NULL)
3578 /* 1.1.1 */
3579 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3580 else if ((typeDecl->subtypes->subtypes == NULL) &&
3581 ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3582 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3583 /* 1.1.2 */
3584 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3585 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3586 (typeDecl->subtypes->subtypes == NULL))
3587 /* 1.1.3 */
3588 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3590 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3591 typeDecl->baseNs);
3592 if (base == NULL) {
3593 xmlSchemaErrorContext(ctxt, NULL, typeDecl->node, NULL);
3594 if ((ctxt != NULL) && (ctxt->error != NULL))
3595 ctxt->error(ctxt->userData,
3596 "Schemas: base type %s of type %s not found\n",
3597 typeDecl->base, name);
3598 return;
3600 xmlSchemaTypeFixup(base, ctxt, NULL);
3601 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
3602 /* 2.1 */
3603 typeDecl->contentType = base->contentType;
3604 } else if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
3605 /* 2.2 imbitable ! */
3606 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3607 } else {
3608 /* 2.3 imbitable pareil ! */
3609 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3611 break;
3613 case XML_SCHEMA_TYPE_COMPLEX: {
3614 if (typeDecl->subtypes == NULL) {
3615 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3616 } else {
3617 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3618 typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3619 else {
3620 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3621 typeDecl->contentType = typeDecl->subtypes->contentType;
3624 break;
3626 case XML_SCHEMA_TYPE_COMPLEX_CONTENT: {
3627 if (typeDecl->subtypes == NULL) {
3628 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3629 } else {
3630 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3631 typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3632 else {
3633 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3634 typeDecl->contentType = typeDecl->subtypes->contentType;
3637 break;
3639 case XML_SCHEMA_TYPE_SEQUENCE:
3640 case XML_SCHEMA_TYPE_GROUP:
3641 case XML_SCHEMA_TYPE_ALL:
3642 case XML_SCHEMA_TYPE_CHOICE:
3643 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3644 break;
3645 case XML_SCHEMA_TYPE_BASIC:
3646 case XML_SCHEMA_TYPE_ANY:
3647 case XML_SCHEMA_TYPE_FACET:
3648 case XML_SCHEMA_TYPE_SIMPLE:
3649 case XML_SCHEMA_TYPE_UR:
3650 case XML_SCHEMA_TYPE_ELEMENT:
3651 case XML_SCHEMA_TYPE_ATTRIBUTE:
3652 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
3653 case XML_SCHEMA_TYPE_NOTATION:
3654 case XML_SCHEMA_TYPE_LIST:
3655 case XML_SCHEMA_TYPE_UNION:
3656 case XML_SCHEMA_FACET_MININCLUSIVE:
3657 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3658 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3659 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
3660 case XML_SCHEMA_FACET_TOTALDIGITS:
3661 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3662 case XML_SCHEMA_FACET_PATTERN:
3663 case XML_SCHEMA_FACET_ENUMERATION:
3664 case XML_SCHEMA_FACET_WHITESPACE:
3665 case XML_SCHEMA_FACET_LENGTH:
3666 case XML_SCHEMA_FACET_MAXLENGTH:
3667 case XML_SCHEMA_FACET_MINLENGTH:
3668 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
3669 break;
3672 #ifdef DEBUG_TYPE
3673 if (typeDecl->node != NULL) {
3674 xmlGenericError(xmlGenericErrorContext,
3675 "Type of %s : %s:%d :", name, typeDecl->node->doc->URL,
3676 xmlGetLineNo(typeDecl->node));
3677 } else {
3678 xmlGenericError(xmlGenericErrorContext,
3679 "Type of %s :", name);
3681 switch (typeDecl->contentType) {
3682 case XML_SCHEMA_CONTENT_SIMPLE:
3683 xmlGenericError(xmlGenericErrorContext,
3684 "simple\n"); break;
3685 case XML_SCHEMA_CONTENT_ELEMENTS:
3686 xmlGenericError(xmlGenericErrorContext,
3687 "elements\n"); break;
3688 case XML_SCHEMA_CONTENT_UNKNOWN:
3689 xmlGenericError(xmlGenericErrorContext,
3690 "unknown !!!\n"); break;
3691 case XML_SCHEMA_CONTENT_EMPTY:
3692 xmlGenericError(xmlGenericErrorContext,
3693 "empty\n"); break;
3694 case XML_SCHEMA_CONTENT_MIXED:
3695 xmlGenericError(xmlGenericErrorContext,
3696 "mixed\n"); break;
3697 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
3698 xmlGenericError(xmlGenericErrorContext,
3699 "mixed or elems\n"); break;
3700 case XML_SCHEMA_CONTENT_BASIC:
3701 xmlGenericError(xmlGenericErrorContext,
3702 "basic\n"); break;
3703 default:
3704 xmlGenericError(xmlGenericErrorContext,
3705 "not registered !!!\n"); break;
3707 #endif
3711 * xmlSchemaCheckDefaults:
3712 * @typeDecl: the schema type definition
3713 * @ctxt: the schema parser context
3715 * Checks the default values types, especially for facets
3717 static void
3718 xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
3719 xmlSchemaParserCtxtPtr ctxt,
3720 const xmlChar *name)
3722 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
3723 if (name == NULL)
3724 name = typeDecl->name;
3725 if (nonNegativeIntegerType == NULL) {
3726 nonNegativeIntegerType = xmlSchemaGetPredefinedType(
3727 BAD_CAST "nonNegativeInteger", xmlSchemaNs);
3729 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
3730 if (typeDecl->facets != NULL) {
3731 xmlSchemaFacetPtr facet = typeDecl->facets;
3732 while (facet != NULL) {
3733 switch (facet->type) {
3734 case XML_SCHEMA_FACET_MININCLUSIVE:
3735 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3736 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3737 case XML_SCHEMA_FACET_MAXEXCLUSIVE: {
3739 * Okay we need to validate the value
3740 * at that point.
3742 xmlSchemaValidCtxtPtr vctxt;
3744 vctxt = xmlSchemaNewValidCtxt(NULL);
3745 if (vctxt == NULL)
3746 break;
3747 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3748 facet->value);
3749 facet->val = vctxt->value;
3750 vctxt->value = NULL;
3751 if (facet->val == NULL) {
3752 /* error code */
3753 xmlSchemaErrorContext(ctxt, NULL,
3754 facet->node, NULL);
3755 ctxt->error(ctxt->userData,
3756 "Schemas: type %s facet value %s invalid\n",
3757 name, facet->value);
3759 xmlSchemaFreeValidCtxt(vctxt);
3760 break;
3762 case XML_SCHEMA_FACET_ENUMERATION: {
3764 * Okay we need to validate the value
3765 * at that point.
3767 xmlSchemaValidCtxtPtr vctxt;
3768 int ret;
3770 vctxt = xmlSchemaNewValidCtxt(NULL);
3771 if (vctxt == NULL)
3772 break;
3773 ret = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3774 facet->value);
3775 if (ret != 0) {
3776 xmlSchemaErrorContext(ctxt, NULL,
3777 facet->node, NULL);
3778 ctxt->error(ctxt->userData,
3779 "Schemas: type %s enumeration value %s invalid\n",
3780 name, facet->value);
3782 xmlSchemaFreeValidCtxt(vctxt);
3783 break;
3785 case XML_SCHEMA_FACET_PATTERN:
3786 facet->regexp = xmlRegexpCompile(facet->value);
3787 if (facet->regexp == NULL) {
3788 /* error code */
3789 ctxt->error(ctxt->userData,
3790 "Schemas: type %s facet regexp %s invalid\n",
3791 name, facet->value);
3793 break;
3794 case XML_SCHEMA_FACET_TOTALDIGITS:
3795 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3796 case XML_SCHEMA_FACET_LENGTH:
3797 case XML_SCHEMA_FACET_MAXLENGTH:
3798 case XML_SCHEMA_FACET_MINLENGTH: {
3799 int ret;
3801 ret = xmlSchemaValidatePredefinedType(
3802 nonNegativeIntegerType, facet->value,
3803 &facet->val);
3804 if (ret != 0) {
3805 /* error code */
3806 xmlSchemaErrorContext(ctxt, NULL,
3807 facet->node, NULL);
3808 ctxt->error(ctxt->userData,
3809 "Schemas: type %s facet value %s invalid\n",
3810 name, facet->value);
3812 break;
3814 case XML_SCHEMA_FACET_WHITESPACE: {
3815 if (xmlStrEqual(facet->value, BAD_CAST"preserve")) {
3816 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
3817 } else if (xmlStrEqual(facet->value,
3818 BAD_CAST"replace")) {
3819 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
3820 } else if (xmlStrEqual(facet->value,
3821 BAD_CAST"collapse")) {
3822 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
3823 } else {
3824 xmlSchemaErrorContext(ctxt, NULL,
3825 facet->node, NULL);
3826 ctxt->error(ctxt->userData,
3827 "Schemas: type %s whiteSpace value %s invalid\n",
3828 name, facet->value);
3831 default:
3832 break;
3834 facet = facet->next;
3841 * xmlSchemaAttrGrpFixup:
3842 * @attrgrpDecl: the schema attribute definition
3843 * @ctxt: the schema parser context
3844 * @name: the attribute name
3846 * Fixes finish doing the computations on the attributes definitions
3848 static void
3849 xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
3850 xmlSchemaParserCtxtPtr ctxt,
3851 const xmlChar *name)
3853 if (name == NULL)
3854 name = attrgrpDecl->name;
3855 if (attrgrpDecl->attributes != NULL)
3856 return;
3857 if (attrgrpDecl->ref != NULL) {
3858 xmlSchemaAttributeGroupPtr ref;
3860 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
3861 attrgrpDecl->refNs);
3862 if (ref == NULL) {
3863 if ((ctxt != NULL) && (ctxt->error != NULL))
3864 ctxt->error(ctxt->userData,
3865 "Schemas: attribute group %s reference %s not found\n",
3866 name, attrgrpDecl->ref);
3867 return;
3869 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
3870 attrgrpDecl->attributes = ref->attributes;
3871 } else {
3872 if ((ctxt != NULL) && (ctxt->error != NULL))
3873 ctxt->error(ctxt->userData,
3874 "Schemas: attribute %s has no attributes nor reference\n",
3875 name);
3880 * xmlSchemaAttrFixup:
3881 * @attrDecl: the schema attribute definition
3882 * @ctxt: the schema parser context
3883 * @name: the attribute name
3885 * Fixes finish doing the computations on the attributes definitions
3887 static void
3888 xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
3889 xmlSchemaParserCtxtPtr ctxt,
3890 const xmlChar *name)
3892 if (name == NULL)
3893 name = attrDecl->name;
3894 if (attrDecl->subtypes != NULL)
3895 return;
3896 if (attrDecl->typeName != NULL) {
3897 xmlSchemaTypePtr type;
3899 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
3900 attrDecl->typeNs);
3901 if (type == NULL) {
3902 if ((ctxt != NULL) && (ctxt->error != NULL))
3903 ctxt->error(ctxt->userData,
3904 "Schemas: attribute %s type %s not found\n",
3905 name, attrDecl->typeName);
3907 attrDecl->subtypes = type;
3908 } else if (attrDecl->ref != NULL) {
3909 xmlSchemaAttributePtr ref;
3911 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
3912 attrDecl->refNs);
3913 if (ref == NULL) {
3914 if ((ctxt != NULL) && (ctxt->error != NULL))
3915 ctxt->error(ctxt->userData,
3916 "Schemas: attribute %s reference %s not found\n",
3917 name, attrDecl->ref);
3918 return;
3920 xmlSchemaAttrFixup(ref, ctxt, NULL);
3921 attrDecl->subtypes = ref->subtypes;
3922 } else {
3923 if ((ctxt != NULL) && (ctxt->error != NULL))
3924 ctxt->error(ctxt->userData,
3925 "Schemas: attribute %s has no type nor reference\n",
3926 name);
3931 * xmlSchemaParse:
3932 * @ctxt: a schema validation context
3933 * @URL: the location of the schema
3935 * Load, XML parse a schema definition resource and build an internal
3936 * XML Shema struture which can be used to validate instances.
3937 * *WARNING* this interface is highly subject to change
3939 * Returns the internal XML Schema structure built from the resource or
3940 * NULL in case of error
3942 xmlSchemaPtr
3943 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
3945 xmlSchemaPtr ret = NULL;
3946 xmlDocPtr doc;
3947 xmlNodePtr root, cur, delete;
3949 xmlSchemaInitTypes();
3951 if (ctxt == NULL)
3952 return (NULL);
3954 ctxt->counter = 0;
3955 ctxt->container = NULL;
3958 * First step is to parse the input document into an DOM/Infoset
3960 if (ctxt->URL != NULL) {
3961 doc = xmlParseFile((const char *) ctxt->URL);
3962 if (doc == NULL) {
3963 if (ctxt->error != NULL)
3964 ctxt->error(ctxt->userData,
3965 "xmlSchemaParse: could not load %s\n", ctxt->URL);
3966 return (NULL);
3968 } else if (ctxt->buffer != NULL) {
3969 doc = xmlParseMemory(ctxt->buffer, ctxt->size);
3970 if (doc == NULL) {
3971 if (ctxt->error != NULL)
3972 ctxt->error(ctxt->userData,
3973 "xmlSchemaParse: could not parse schemas\n");
3974 return (NULL);
3976 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
3977 ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
3978 } else {
3979 if (ctxt->error != NULL)
3980 ctxt->error(ctxt->userData,
3981 "xmlSchemaParse: nothing to parse\n");
3982 return (NULL);
3986 * Then extract the root and Schema parse it
3988 root = xmlDocGetRootElement(doc);
3989 if (root == NULL) {
3990 if (ctxt->error != NULL)
3991 ctxt->error(ctxt->userData, "xmlSchemaParse: %s is empty\n",
3992 ctxt->URL);
3993 return (NULL);
3997 * Remove all the blank text nodes
3999 delete = NULL;
4000 cur = root;
4001 while (cur != NULL) {
4002 if (delete != NULL) {
4003 xmlUnlinkNode(delete);
4004 xmlFreeNode(delete);
4005 delete = NULL;
4007 if (cur->type == XML_TEXT_NODE) {
4008 if (IS_BLANK_NODE(cur)) {
4009 if (xmlNodeGetSpacePreserve(cur) != 1) {
4010 delete = cur;
4013 } else if ((cur->type != XML_ELEMENT_NODE) &&
4014 (cur->type != XML_CDATA_SECTION_NODE)) {
4015 delete = cur;
4016 goto skip_children;
4020 * Skip to next node
4022 if (cur->children != NULL) {
4023 if ((cur->children->type != XML_ENTITY_DECL) &&
4024 (cur->children->type != XML_ENTITY_REF_NODE) &&
4025 (cur->children->type != XML_ENTITY_NODE)) {
4026 cur = cur->children;
4027 continue;
4030 skip_children:
4031 if (cur->next != NULL) {
4032 cur = cur->next;
4033 continue;
4036 do {
4037 cur = cur->parent;
4038 if (cur == NULL)
4039 break;
4040 if (cur == root) {
4041 cur = NULL;
4042 break;
4044 if (cur->next != NULL) {
4045 cur = cur->next;
4046 break;
4048 } while (cur != NULL);
4050 if (delete != NULL) {
4051 xmlUnlinkNode(delete);
4052 xmlFreeNode(delete);
4053 delete = NULL;
4057 * Then do the parsing for good
4059 ret = xmlSchemaParseSchema(ctxt, root);
4060 if (ret == NULL)
4061 return(NULL);
4062 ret->doc = doc;
4065 * Then fix all the references.
4067 ctxt->schema = ret;
4068 xmlHashScanFull(ret->elemDecl,
4069 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
4072 * Then fixup all types properties
4074 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4077 * Then build the content model for all elements
4079 xmlHashScan(ret->elemDecl,
4080 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
4083 * Then check the defaults part of the type like facets values
4085 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt);
4088 * Then fixup all attributes declarations
4090 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4093 * Then fixup all attributes group declarations
4095 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup, ctxt);
4097 return (ret);
4101 * xmlSchemaParse:
4102 * @ctxt: a schema validation context
4103 * @URL: the location of the schema
4105 * Load, XML parse a schema definition resource and build an internal
4106 * XML Shema struture which can be used to validate instances.
4107 * *WARNING* this interface is highly subject to change
4109 * Returns the internal XML Schema structure built from the resource or
4110 * NULL in case of error
4112 void
4113 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
4114 xmlSchemaValidityErrorFunc err,
4115 xmlSchemaValidityWarningFunc warn, void *ctx) {
4116 if (ctxt == NULL)
4117 return;
4118 ctxt->error = err;
4119 ctxt->warning = warn;
4120 ctxt->userData = ctx;
4123 /************************************************************************
4125 * Simple type validation *
4127 ************************************************************************/
4130 * xmlSchemaValidateSimpleValue:
4131 * @ctxt: a schema validation context
4132 * @type: the type declaration
4133 * @value: the value to validate
4135 * Validate a value against a simple type
4137 * Returns 0 if the value is valid, a positive error code
4138 * number otherwise and -1 in case of internal or API error.
4140 static int
4141 xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
4142 xmlSchemaTypePtr type,
4143 xmlChar *value) {
4144 int ret = 0;
4146 * First normalize the value accordingly to Schema Datatype
4147 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
4150 * Then check the normalized value against the lexical space of the
4151 * type.
4153 if (type->type == XML_SCHEMA_TYPE_BASIC) {
4154 if (ctxt->value != NULL) {
4155 xmlSchemaFreeValue(ctxt->value);
4156 ctxt->value = NULL;
4158 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
4159 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
4160 xmlSchemaTypePtr base;
4161 xmlSchemaFacetPtr facet;
4162 int tmp;
4164 base = type->baseType;
4165 if (base != NULL) {
4166 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4167 } else if (type->subtypes != NULL) {
4171 * Do not validate facets when working on building the Schemas
4173 if (ctxt->schema != NULL) {
4174 if (ret == 0) {
4175 facet = type->facets;
4176 if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) &&
4177 (facet != NULL) &&
4178 (facet->type == XML_SCHEMA_FACET_ENUMERATION)) {
4179 while (facet != NULL) {
4180 ret = 1;
4182 tmp = xmlSchemaValidateFacet(base, facet, value,
4183 ctxt->value);
4184 if (tmp == 0) {
4185 ret = 0;
4186 break;
4188 facet = facet->next;
4190 } else {
4191 while (facet != NULL) {
4192 tmp = xmlSchemaValidateFacet(base, facet, value,
4193 ctxt->value);
4194 if (tmp != 0)
4195 ret = tmp;
4196 facet = facet->next;
4201 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
4202 xmlSchemaTypePtr base;
4204 base = type->subtypes;
4205 if (base != NULL) {
4206 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4207 } else {
4208 TODO
4210 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
4211 xmlSchemaTypePtr base;
4212 xmlChar *cur, *end, tmp;
4213 int ret2;
4215 base = type->subtypes;
4216 if (base == NULL) {
4217 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4218 if (ctxt->error != NULL) {
4219 xmlSchemaErrorContext(NULL, ctxt->schema, type->node, NULL);
4220 ctxt->error(ctxt->userData,
4221 "Internal: List type %s has no base type\n",
4222 type->name);
4224 return(-1);
4226 cur = value;
4227 do {
4228 while (IS_BLANK(*cur)) cur++;
4229 end = cur;
4230 while ((*end != 0) && (!(IS_BLANK(*end)))) end++;
4231 if (end == cur)
4232 break;
4233 tmp = *end;
4234 *end = 0;
4235 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, cur);
4236 if (ret2 != 0)
4237 ret = 1;
4238 *end = tmp;
4239 cur = end;
4240 } while (*cur != 0);
4241 } else {
4242 TODO
4244 return(ret);
4247 /************************************************************************
4249 * DOM Validation code *
4251 ************************************************************************/
4253 static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
4254 xmlNodePtr node);
4255 static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
4256 xmlNodePtr elem, xmlSchemaAttributePtr attributes);
4257 static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
4258 xmlNodePtr elem, xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type);
4261 * xmlSchemaRegisterAttributes:
4262 * @ctxt: a schema validation context
4263 * @attrs: a list of attributes
4265 * Register the list of attributes as the set to be validated on that element
4267 * Returns -1 in case of error, 0 otherwise
4269 static int
4270 xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt,
4271 xmlAttrPtr attrs) {
4272 while (attrs != NULL) {
4273 if ((attrs->ns != NULL) &&
4274 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
4275 attrs = attrs->next;
4276 continue;
4278 if (ctxt->attrNr >= ctxt->attrMax) {
4279 xmlSchemaAttrStatePtr tmp;
4281 ctxt->attrMax *= 2;
4282 tmp = (xmlSchemaAttrStatePtr)
4283 xmlRealloc(ctxt->attr, ctxt->attrMax *
4284 sizeof(xmlSchemaAttrState));
4285 if (tmp == NULL) {
4286 ctxt->attrMax /= 2;
4287 return(-1);
4289 ctxt->attr = tmp;
4291 ctxt->attr[ctxt->attrNr].attr = attrs;
4292 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
4293 ctxt->attrNr++;
4294 attrs = attrs->next;
4296 return(0);
4300 * xmlSchemaCheckAttributes:
4301 * @ctxt: a schema validation context
4302 * @node: the node carrying it.
4304 * Check that the registered set of attributes on the current node
4305 * has been properly validated.
4307 * Returns 0 if validity constraints are met, 1 otherwise.
4309 static int
4310 xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4311 int ret = 0;
4312 int i;
4314 for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
4315 if (ctxt->attr[i].attr == NULL)
4316 break;
4317 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
4318 ret = 1;
4319 ctxt->err = XML_SCHEMAS_ERR_ATTRUNKNOWN;
4320 if (ctxt->error != NULL)
4321 ctxt->error(ctxt->userData,
4322 "Attribute %s on %s is unknown\n",
4323 ctxt->attr[i].attr->name,
4324 node->name);
4327 return(ret);
4331 * xmlSchemaValidateSimpleContent:
4332 * @ctxt: a schema validation context
4333 * @elem: an element
4334 * @type: the type declaration
4336 * Validate the content of an element expected to be a simple type
4338 * Returns 0 if the element is schemas valid, a positive error code
4339 * number otherwise and -1 in case of internal or API error.
4341 static int
4342 xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
4343 xmlNodePtr node ATTRIBUTE_UNUSED) {
4344 xmlNodePtr child;
4345 xmlSchemaTypePtr type, base;
4346 xmlChar *value;
4347 int ret = 0, tmp;
4349 child = ctxt->node;
4350 type = ctxt->type;
4353 * Validation Rule: Element Locally Valid (Type): 3.1.3
4355 value = xmlNodeGetContent(child);
4356 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
4357 switch (type->type) {
4358 case XML_SCHEMA_TYPE_RESTRICTION: {
4359 xmlSchemaFacetPtr facet;
4361 base = type->baseType;
4362 if (base != NULL) {
4363 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4364 } else {
4365 TODO
4367 if (ret == 0) {
4368 facet = type->facets;
4369 while (facet != NULL) {
4370 tmp = xmlSchemaValidateFacet(base, facet, value,
4371 ctxt->value);
4372 if (tmp != 0)
4373 ret = tmp;
4374 facet = facet->next;
4377 break;
4379 default:
4380 TODO
4382 if (value != NULL)
4383 xmlFree(value);
4385 return(ret);
4389 * xmlSchemaValidateCheckNodeList
4390 * @nodelist: the list of nodes
4392 * Check the node list is only made of text nodes and entities pointing
4393 * to text nodes
4395 * Returns 1 if true, 0 if false and -1 in case of error
4397 static int
4398 xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist) {
4399 while (nodelist != NULL) {
4400 if (nodelist->type == XML_ENTITY_REF_NODE) {
4401 TODO /* implement recursion in the entity content */
4403 if ((nodelist->type != XML_TEXT_NODE) &&
4404 (nodelist->type != XML_COMMENT_NODE) &&
4405 (nodelist->type != XML_PI_NODE) &&
4406 (nodelist->type != XML_PI_NODE)) {
4407 return(0);
4409 nodelist = nodelist->next;
4411 return(1);
4415 * xmlSchemaSkipIgnored:
4416 * @ctxt: a schema validation context
4417 * @type: the current type context
4418 * @node: the top node.
4420 * Skip ignorable nodes in that context
4422 * Returns the new sibling
4423 * number otherwise and -1 in case of internal or API error.
4425 static xmlNodePtr
4426 xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
4427 xmlSchemaTypePtr type,
4428 xmlNodePtr node) {
4429 int mixed = 0;
4431 * TODO complete and handle entities
4433 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
4434 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
4435 while ((node != NULL) &&
4436 ((node->type == XML_COMMENT_NODE) ||
4437 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
4438 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
4439 (node->type == XML_TEXT_NODE) &&
4440 (IS_BLANK_NODE(node)))))) {
4441 node = node->next;
4443 return(node);
4447 * xmlSchemaValidateCallback:
4448 * @ctxt: a schema validation context
4449 * @name: the name of the element detected (might be NULL)
4450 * @type: the type
4452 * A transition has been made in the automata associated to an element
4453 * content model
4455 static void
4456 xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
4457 const xmlChar *name ATTRIBUTE_UNUSED,
4458 xmlSchemaTypePtr type,
4459 xmlNodePtr node) {
4460 xmlSchemaTypePtr oldtype = ctxt->type;
4461 xmlNodePtr oldnode = ctxt->node;
4462 #ifdef DEBUG_CONTENT
4463 xmlGenericError(xmlGenericErrorContext,
4464 "xmlSchemaValidateCallback: %s, %s, %s\n",
4465 name, type->name, node->name);
4466 #endif
4467 ctxt->type = type;
4468 ctxt->node = node;
4469 xmlSchemaValidateContent(ctxt, node);
4470 ctxt->type = oldtype;
4471 ctxt->node = oldnode;
4475 #if 0
4477 * xmlSchemaValidateSimpleRestrictionType:
4478 * @ctxt: a schema validation context
4479 * @node: the top node.
4481 * Validate the content of a restriction type.
4483 * Returns 0 if the element is schemas valid, a positive error code
4484 * number otherwise and -1 in case of internal or API error.
4486 static int
4487 xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
4488 xmlNodePtr node)
4490 xmlNodePtr child;
4491 xmlSchemaTypePtr type;
4492 int ret;
4494 child = ctxt->node;
4495 type = ctxt->type;
4497 if ((ctxt == NULL) || (type == NULL)) {
4498 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4499 if (ctxt->error != NULL)
4500 ctxt->error(ctxt->userData,
4501 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
4502 node->name);
4503 return (-1);
4506 * Only text and text based entities references shall be found there
4508 ret = xmlSchemaValidateCheckNodeList(child);
4509 if (ret < 0) {
4510 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4511 if (ctxt->error != NULL)
4512 ctxt->error(ctxt->userData,
4513 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4514 node->name);
4515 return (-1);
4516 } else if (ret == 0) {
4517 ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4518 if (ctxt->error != NULL)
4519 ctxt->error(ctxt->userData,
4520 "Element %s content is not a simple type\n",
4521 node->name);
4522 return (-1);
4524 ctxt->type = type->subtypes;
4525 xmlSchemaValidateContent(ctxt, node);
4526 ctxt->type = type;
4527 return (ret);
4529 #endif
4532 * xmlSchemaValidateSimpleType:
4533 * @ctxt: a schema validation context
4534 * @node: the top node.
4536 * Validate the content of an simple type.
4538 * Returns 0 if the element is schemas valid, a positive error code
4539 * number otherwise and -1 in case of internal or API error.
4541 static int
4542 xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4543 xmlNodePtr child;
4544 xmlSchemaTypePtr type;
4545 xmlAttrPtr attr;
4546 int ret;
4548 child = ctxt->node;
4549 type = ctxt->type;
4551 if ((ctxt == NULL) || (type == NULL)) {
4552 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4553 if (ctxt->error != NULL)
4554 ctxt->error(ctxt->userData,
4555 "Internal error: xmlSchemaValidateSimpleType %s\n",
4556 node->name);
4557 return(-1);
4560 * Only text and text based entities references shall be found there
4562 ret = xmlSchemaValidateCheckNodeList(child);
4563 if (ret < 0) {
4564 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4565 if (ctxt->error != NULL)
4566 ctxt->error(ctxt->userData,
4567 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4568 node->name);
4569 return(-1);
4570 } else if (ret == 0) {
4571 ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4572 if (ctxt->error != NULL)
4573 ctxt->error(ctxt->userData,
4574 "Element %s content is not a simple type\n",
4575 node->name);
4576 return(-1);
4579 * Validation Rule: Element Locally Valid (Type): 3.1.1
4581 attr = node->properties;
4582 while (attr != NULL) {
4583 if ((attr->ns == NULL) ||
4584 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
4585 ((!xmlStrEqual(attr->name, BAD_CAST"type")) &&
4586 (!xmlStrEqual(attr->name, BAD_CAST"nil")) &&
4587 (!xmlStrEqual(attr->name, BAD_CAST"schemasLocation")) &&
4588 (!xmlStrEqual(attr->name, BAD_CAST"noNamespaceSchemaLocation")))) {
4589 ctxt->err = XML_SCHEMAS_ERR_INVALIDATTR;
4590 if (ctxt->error != NULL)
4591 ctxt->error(ctxt->userData,
4592 "Element %s: attribute %s should not be present\n",
4593 child->name, attr->name);
4594 return(ctxt->err);
4598 ctxt->type = type->subtypes;
4599 ret = xmlSchemaValidateSimpleContent(ctxt, node);
4600 ctxt->type = type;
4601 return(ret);
4605 * xmlSchemaValidateElementType:
4606 * @ctxt: a schema validation context
4607 * @node: the top node.
4609 * Validate the content of an element type.
4610 * Validation Rule: Element Locally Valid (Complex Type)
4612 * Returns 0 if the element is schemas valid, a positive error code
4613 * number otherwise and -1 in case of internal or API error.
4615 static int
4616 xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4617 xmlNodePtr child;
4618 xmlSchemaTypePtr type;
4619 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
4620 xmlSchemaElementPtr decl;
4621 int ret, attrBase;
4623 oldregexp = ctxt->regexp;
4625 child = ctxt->node;
4626 type = ctxt->type;
4628 if ((ctxt == NULL) || (type == NULL)) {
4629 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4630 if (ctxt->error != NULL)
4631 ctxt->error(ctxt->userData,
4632 "Internal error: xmlSchemaValidateElementType\n",
4633 node->name);
4634 return(-1);
4636 if (child == NULL) {
4637 if (type->minOccurs > 0) {
4638 ctxt->err = XML_SCHEMAS_ERR_MISSING;
4639 if (ctxt->error != NULL)
4640 ctxt->error(ctxt->userData,
4641 "Element %s: missing child %s\n",
4642 node->name, type->name);
4644 return(ctxt->err);
4648 * Verify the element matches
4650 if (!xmlStrEqual(child->name, type->name)) {
4651 ctxt->err = XML_SCHEMAS_ERR_WRONGELEM;
4652 if (ctxt->error != NULL)
4653 ctxt->error(ctxt->userData,
4654 "Element %s: missing child %s found %s\n",
4655 node->name, type->name, child->name);
4656 return(ctxt->err);
4659 * Verify the attributes
4661 attrBase = ctxt->attrBase;
4662 ctxt->attrBase = ctxt->attrNr;
4663 xmlSchemaRegisterAttributes(ctxt, child->properties);
4664 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
4666 * Verify the element content recursively
4668 decl = (xmlSchemaElementPtr) type;
4669 oldregexp = ctxt->regexp;
4670 if (decl->contModel != NULL) {
4671 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
4672 (xmlRegExecCallbacks) xmlSchemaValidateCallback,
4673 ctxt);
4674 #ifdef DEBUG_AUTOMATA
4675 xmlGenericError(xmlGenericErrorContext,
4676 "====> %s\n", node->name);
4677 #endif
4679 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr)type,
4680 type->subtypes);
4682 if (decl->contModel != NULL) {
4683 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
4684 #ifdef DEBUG_AUTOMATA
4685 xmlGenericError(xmlGenericErrorContext,
4686 "====> %s : %d\n", node->name, ret);
4687 #endif
4688 if (ret == 0) {
4689 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
4690 if (ctxt->error != NULL)
4691 ctxt->error(ctxt->userData, "Element %s content check failed\n",
4692 node->name);
4693 } else if (ret < 0) {
4694 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
4695 if (ctxt->error != NULL)
4696 ctxt->error(ctxt->userData, "Element %s content check failure\n",
4697 node->name);
4698 #ifdef DEBUG_CONTENT
4699 } else {
4700 xmlGenericError(xmlGenericErrorContext,
4701 "Element %s content check succeeded\n", node->name);
4703 #endif
4705 xmlRegFreeExecCtxt(ctxt->regexp);
4708 * Verify that all attributes were Schemas-validated
4710 xmlSchemaCheckAttributes(ctxt, node);
4711 ctxt->attrNr = ctxt->attrBase;
4712 ctxt->attrBase = attrBase;
4714 ctxt->regexp = oldregexp;
4716 ctxt->node = child;
4717 ctxt->type = type;
4718 return(ctxt->err);
4722 * xmlSchemaValidateBasicType:
4723 * @ctxt: a schema validation context
4724 * @node: the top node.
4726 * Validate the content of an element expected to be a basic type type
4728 * Returns 0 if the element is schemas valid, a positive error code
4729 * number otherwise and -1 in case of internal or API error.
4731 static int
4732 xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4733 int ret;
4734 xmlNodePtr child, cur;
4735 xmlSchemaTypePtr type;
4736 xmlChar *value; /* lexical representation */
4738 child = ctxt->node;
4739 type = ctxt->type;
4741 if ((ctxt == NULL) || (type == NULL)) {
4742 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4743 if (ctxt->error != NULL)
4744 ctxt->error(ctxt->userData,
4745 "Internal error: xmlSchemaValidateBasicType\n",
4746 node->name);
4747 return(-1);
4750 * First check the content model of the node.
4752 cur = child;
4753 while (cur != NULL) {
4754 switch (cur->type) {
4755 case XML_TEXT_NODE:
4756 case XML_CDATA_SECTION_NODE:
4757 case XML_PI_NODE:
4758 case XML_COMMENT_NODE:
4759 case XML_XINCLUDE_START:
4760 case XML_XINCLUDE_END:
4761 break;
4762 case XML_ENTITY_REF_NODE:
4763 case XML_ENTITY_NODE:
4764 TODO
4765 break;
4766 case XML_ELEMENT_NODE:
4767 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
4768 if (ctxt->error != NULL)
4769 ctxt->error(ctxt->userData,
4770 "Element %s: child %s should not be present\n",
4771 node->name, cur->name);
4772 return(ctxt->err);
4773 case XML_ATTRIBUTE_NODE:
4774 case XML_DOCUMENT_NODE:
4775 case XML_DOCUMENT_TYPE_NODE:
4776 case XML_DOCUMENT_FRAG_NODE:
4777 case XML_NOTATION_NODE:
4778 case XML_HTML_DOCUMENT_NODE:
4779 case XML_DTD_NODE:
4780 case XML_ELEMENT_DECL:
4781 case XML_ATTRIBUTE_DECL:
4782 case XML_ENTITY_DECL:
4783 case XML_NAMESPACE_DECL:
4784 #ifdef LIBXML_DOCB_ENABLED
4785 case XML_DOCB_DOCUMENT_NODE:
4786 #endif
4787 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
4788 if (ctxt->error != NULL)
4789 ctxt->error(ctxt->userData,
4790 "Element %s: node type %d unexpected here\n",
4791 node->name, cur->type);
4792 return(ctxt->err);
4794 cur = cur->next;
4796 if (child == NULL)
4797 value = NULL;
4798 else
4799 value = xmlNodeGetContent(child->parent);
4801 if (ctxt->value != NULL) {
4802 xmlSchemaFreeValue(ctxt->value);
4803 ctxt->value = NULL;
4805 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
4806 if (value != NULL)
4807 xmlFree(value);
4808 if (ret != 0) {
4809 ctxt->error(ctxt->userData,
4810 "Element %s: failed to validate basic type %s\n",
4811 node->name, type->name);
4813 return(ret);
4817 * xmlSchemaValidateComplexType:
4818 * @ctxt: a schema validation context
4819 * @node: the top node.
4821 * Validate the content of an element expected to be a complex type type
4822 * xmlschema-1.html#cvc-complex-type
4823 * Validation Rule: Element Locally Valid (Complex Type)
4825 * Returns 0 if the element is schemas valid, a positive error code
4826 * number otherwise and -1 in case of internal or API error.
4828 static int
4829 xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4830 xmlNodePtr child;
4831 xmlSchemaTypePtr type, subtype;
4832 int ret;
4834 child = ctxt->node;
4835 type = ctxt->type;
4837 switch (type->contentType) {
4838 case XML_SCHEMA_CONTENT_EMPTY:
4839 if (child != NULL) {
4840 if (ctxt->error != NULL)
4841 ctxt->error(ctxt->userData,
4842 "Element %s is supposed to be empty\n",
4843 node->name);
4845 if (type->attributes != NULL) {
4846 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4848 subtype = type->subtypes;
4849 while (subtype != NULL) {
4850 ctxt->type = subtype;
4851 xmlSchemaValidateComplexType(ctxt, node);
4852 subtype = subtype->next;
4854 break;
4855 case XML_SCHEMA_CONTENT_ELEMENTS:
4856 case XML_SCHEMA_CONTENT_MIXED:
4857 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4859 * Skip ignorable nodes in that context
4861 child = xmlSchemaSkipIgnored(ctxt, type, child);
4862 while (child != NULL) {
4863 if (child->type == XML_ELEMENT_NODE) {
4864 ret = xmlRegExecPushString(ctxt->regexp,
4865 child->name, child);
4866 #ifdef DEBUG_AUTOMATA
4867 if (ret < 0)
4868 xmlGenericError(xmlGenericErrorContext,
4869 " --> %s Error\n", child->name);
4870 else
4871 xmlGenericError(xmlGenericErrorContext,
4872 " --> %s\n", child->name);
4873 #endif
4875 child = child->next;
4877 * Skip ignorable nodes in that context
4879 child = xmlSchemaSkipIgnored(ctxt, type, child);
4881 break;
4882 case XML_SCHEMA_CONTENT_BASIC: {
4883 if (type->subtypes != NULL) {
4884 ctxt->type = type->subtypes;
4885 xmlSchemaValidateComplexType(ctxt, node);
4887 if (type->baseType != NULL) {
4888 ctxt->type = type->baseType;
4889 xmlSchemaValidateBasicType(ctxt, node);
4891 if (type->attributes != NULL) {
4892 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4894 ctxt->type = type;
4895 break;
4897 default:
4898 TODO
4899 xmlGenericError(xmlGenericErrorContext,
4900 "unimplemented content type %d\n",
4901 type->contentType);
4903 return(ctxt->err);
4907 * xmlSchemaValidateContent:
4908 * @ctxt: a schema validation context
4909 * @elem: an element
4910 * @type: the type declaration
4912 * Validate the content of an element against the type.
4914 * Returns 0 if the element is schemas valid, a positive error code
4915 * number otherwise and -1 in case of internal or API error.
4917 static int
4918 xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4919 xmlNodePtr child;
4920 xmlSchemaTypePtr type;
4922 child = ctxt->node;
4923 type = ctxt->type;
4925 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4927 switch (type->type) {
4928 case XML_SCHEMA_TYPE_ANY:
4929 /* Any type will do it, fine */
4930 TODO /* handle recursivity */
4931 break;
4932 case XML_SCHEMA_TYPE_COMPLEX:
4933 xmlSchemaValidateComplexType(ctxt, node);
4934 break;
4935 case XML_SCHEMA_TYPE_ELEMENT: {
4936 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
4938 * Handle element reference here
4940 if (decl->ref != NULL) {
4941 if (decl->refDecl == NULL) {
4942 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4943 if (ctxt->error != NULL)
4944 ctxt->error(ctxt->userData,
4945 "Internal error: element reference %s not resolved\n",
4946 decl->ref);
4947 return(-1);
4949 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
4950 decl = decl->refDecl;
4952 xmlSchemaValidateElementType(ctxt, node);
4953 ctxt->type = type;
4954 break;
4956 case XML_SCHEMA_TYPE_BASIC:
4957 xmlSchemaValidateBasicType(ctxt, node);
4958 break;
4959 case XML_SCHEMA_TYPE_FACET:
4960 TODO
4961 break;
4962 case XML_SCHEMA_TYPE_SIMPLE:
4963 xmlSchemaValidateSimpleType(ctxt, node);
4964 break;
4965 case XML_SCHEMA_TYPE_SEQUENCE:
4966 TODO
4967 break;
4968 case XML_SCHEMA_TYPE_CHOICE:
4969 TODO
4970 break;
4971 case XML_SCHEMA_TYPE_ALL:
4972 TODO
4973 break;
4974 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
4975 TODO
4976 break;
4977 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4978 TODO
4979 break;
4980 case XML_SCHEMA_TYPE_UR:
4981 TODO
4982 break;
4983 case XML_SCHEMA_TYPE_RESTRICTION:
4984 /*xmlSchemaValidateRestrictionType(ctxt, node); */
4985 TODO
4986 break;
4987 case XML_SCHEMA_TYPE_EXTENSION:
4988 TODO
4989 break;
4990 case XML_SCHEMA_TYPE_ATTRIBUTE:
4991 TODO
4992 break;
4993 case XML_SCHEMA_TYPE_GROUP:
4994 TODO
4995 break;
4996 case XML_SCHEMA_TYPE_NOTATION:
4997 TODO
4998 break;
4999 case XML_SCHEMA_TYPE_LIST:
5000 TODO
5001 break;
5002 case XML_SCHEMA_TYPE_UNION:
5003 TODO
5004 break;
5005 case XML_SCHEMA_FACET_MININCLUSIVE:
5006 TODO
5007 break;
5008 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5009 TODO
5010 break;
5011 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5012 TODO
5013 break;
5014 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5015 TODO
5016 break;
5017 case XML_SCHEMA_FACET_TOTALDIGITS:
5018 TODO
5019 break;
5020 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5021 TODO
5022 break;
5023 case XML_SCHEMA_FACET_PATTERN:
5024 TODO
5025 break;
5026 case XML_SCHEMA_FACET_ENUMERATION:
5027 TODO
5028 break;
5029 case XML_SCHEMA_FACET_WHITESPACE:
5030 TODO
5031 break;
5032 case XML_SCHEMA_FACET_LENGTH:
5033 TODO
5034 break;
5035 case XML_SCHEMA_FACET_MAXLENGTH:
5036 TODO
5037 break;
5038 case XML_SCHEMA_FACET_MINLENGTH:
5039 TODO
5040 break;
5041 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5042 TODO
5043 break;
5045 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5047 if (ctxt->node == NULL)
5048 return(ctxt->err);
5049 ctxt->node = ctxt->node->next;
5050 ctxt->type = type->next;
5051 return(ctxt->err);
5055 * xmlSchemaValidateType:
5056 * @ctxt: a schema validation context
5057 * @elem: an element
5058 * @type: the list of type declarations
5060 * Validate the content of an element against the types.
5062 * Returns 0 if the element is schemas valid, a positive error code
5063 * number otherwise and -1 in case of internal or API error.
5065 static int
5066 xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
5067 xmlSchemaElementPtr elemDecl,
5068 xmlSchemaTypePtr type) {
5069 xmlChar *nil;
5071 if ((elem->content == NULL) || (type == NULL) || (elemDecl == NULL))
5072 return(0);
5074 * 3.3.4 : 2
5076 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
5077 ctxt->err = XML_SCHEMAS_ERR_ISABSTRACT;
5078 if (ctxt->error != NULL)
5079 ctxt->error(ctxt->userData, "Element %s is abstract\n", elem->name);
5080 return(ctxt->err);
5083 * 3.3.4: 3
5085 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5086 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
5087 /* 3.3.4: 3.2 */
5088 if (xmlStrEqual(nil, BAD_CAST "true")) {
5089 if (elem->children != NULL) {
5090 ctxt->err = XML_SCHEMAS_ERR_NOTEMPTY;
5091 if (ctxt->error != NULL)
5092 ctxt->error(ctxt->userData, "Element %s is not empty\n",
5093 elem->name);
5094 return(ctxt->err);
5096 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
5097 (elemDecl->value != NULL)) {
5098 ctxt->err = XML_SCHEMAS_ERR_HAVEDEFAULT;
5099 if (ctxt->error != NULL)
5100 ctxt->error(ctxt->userData,
5101 "Empty element %s cannot get a fixed value\n",
5102 elem->name);
5103 return(ctxt->err);
5106 } else {
5107 /* 3.3.4: 3.1 */
5108 if (nil != NULL) {
5109 ctxt->err = XML_SCHEMAS_ERR_NOTNILLABLE;
5110 if (ctxt->error != NULL)
5111 ctxt->error(ctxt->userData,
5112 "Element %s with xs:nil but not nillable\n",
5113 elem->name);
5114 xmlFree(nil);
5115 return(ctxt->err);
5119 /* TODO 3.3.4: 4 if the element carries xs:type*/
5121 ctxt->type = elemDecl->subtypes;
5122 ctxt->node = elem->children;
5123 xmlSchemaValidateContent(ctxt, elem);
5124 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5126 return(ctxt->err);
5131 * xmlSchemaValidateAttributes:
5132 * @ctxt: a schema validation context
5133 * @elem: an element
5134 * @attributes: the list of attribute declarations
5136 * Validate the attributes of an element.
5138 * Returns 0 if the element is schemas valid, a positive error code
5139 * number otherwise and -1 in case of internal or API error.
5141 static int
5142 xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
5143 xmlSchemaAttributePtr attributes) {
5144 int i, ret;
5145 xmlAttrPtr attr;
5146 xmlChar *value;
5147 xmlSchemaAttributeGroupPtr group = NULL;
5149 if (attributes == NULL)
5150 return(0);
5151 while (attributes != NULL) {
5153 * Handle attribute groups
5155 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5156 group = (xmlSchemaAttributeGroupPtr) attributes;
5157 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
5158 attributes = group->next;
5159 continue;
5161 for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
5162 attr = ctxt->attr[i].attr;
5163 if (attr == NULL)
5164 continue;
5165 if (!xmlStrEqual(attr->name, attributes->name))
5166 continue;
5168 * TODO: handle the mess about namespaces here.
5170 if ((attr->ns != NULL) /* || (attributes->ns != NULL) */) {
5171 TODO
5173 if (attributes->subtypes == NULL) {
5174 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
5175 if (ctxt->error != NULL)
5176 ctxt->error(ctxt->userData,
5177 "Internal error: attribute %s type not resolved\n",
5178 attr->name);
5179 continue;
5181 value = xmlNodeListGetString(elem->doc, attr->children, 1);
5182 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
5183 value);
5184 if (ret != 0) {
5185 ctxt->err = XML_SCHEMAS_ERR_ATTRINVALID;
5186 if (ctxt->error != NULL)
5187 ctxt->error(ctxt->userData,
5188 "attribute %s on %s does not match type\n",
5189 attr->name, elem->name);
5190 } else {
5191 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
5193 if (value != NULL) {
5194 xmlFree(value);
5197 attributes = attributes->next;
5199 return(ctxt->err);
5203 * xmlSchemaValidateElement:
5204 * @ctxt: a schema validation context
5205 * @elem: an element
5207 * Validate an element in a tree
5209 * Returns 0 if the element is schemas valid, a positive error code
5210 * number otherwise and -1 in case of internal or API error.
5212 static int
5213 xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem) {
5214 xmlSchemaElementPtr elemDecl;
5215 int ret, attrBase;
5217 if (elem->ns != NULL)
5218 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5219 elem->name, elem->ns->href, NULL);
5220 else
5221 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5222 elem->name, NULL, NULL);
5224 * 3.3.4 : 1
5226 if (elemDecl == NULL) {
5227 ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
5228 if (ctxt->error != NULL)
5229 ctxt->error(ctxt->userData, "Element %s not declared\n",
5230 elem->name);
5231 return(ctxt->err);
5233 if (elemDecl->subtypes == NULL) {
5234 ctxt->err = XML_SCHEMAS_ERR_NOTYPE;
5235 if (ctxt->error != NULL)
5236 ctxt->error(ctxt->userData, "Element %s has no type\n",
5237 elem->name);
5238 return(ctxt->err);
5241 * Verify the attributes
5243 attrBase = ctxt->attrBase;
5244 ctxt->attrBase = ctxt->attrNr;
5245 xmlSchemaRegisterAttributes(ctxt, elem->properties);
5246 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5248 * Verify the element content recursively
5250 if (elemDecl->contModel != NULL) {
5251 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
5252 (xmlRegExecCallbacks) xmlSchemaValidateCallback,
5253 ctxt);
5254 #ifdef DEBUG_AUTOMATA
5255 xmlGenericError(xmlGenericErrorContext,
5256 "====> %s\n", elem->name);
5257 #endif
5259 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
5260 if (elemDecl->contModel != NULL) {
5261 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
5262 #ifdef DEBUG_AUTOMATA
5263 xmlGenericError(xmlGenericErrorContext,
5264 "====> %s : %d\n", elem->name, ret);
5265 #endif
5266 if (ret == 0) {
5267 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
5268 if (ctxt->error != NULL)
5269 ctxt->error(ctxt->userData, "Element %s content check failed\n",
5270 elem->name);
5271 } else if (ret < 0) {
5272 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
5273 if (ctxt->error != NULL)
5274 ctxt->error(ctxt->userData, "Element %s content check failed\n",
5275 elem->name);
5276 #ifdef DEBUG_CONTENT
5277 } else {
5278 xmlGenericError(xmlGenericErrorContext,
5279 "Element %s content check succeeded\n", elem->name);
5281 #endif
5283 xmlRegFreeExecCtxt(ctxt->regexp);
5286 * Verify that all attributes were Schemas-validated
5288 xmlSchemaCheckAttributes(ctxt, elem);
5289 ctxt->attrNr = ctxt->attrBase;
5290 ctxt->attrBase = attrBase;
5292 return(ctxt->err);
5296 * xmlSchemaValidateDocument:
5297 * @ctxt: a schema validation context
5298 * @doc: a parsed document tree
5300 * Validate a document tree in memory.
5302 * Returns 0 if the document is schemas valid, a positive error code
5303 * number otherwise and -1 in case of internal or API error.
5305 static int
5306 xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5307 xmlNodePtr root;
5308 xmlSchemaElementPtr elemDecl;
5310 root = xmlDocGetRootElement(doc);
5311 if (root == NULL) {
5312 ctxt->err = XML_SCHEMAS_ERR_NOROOT;
5313 if (ctxt->error != NULL)
5314 ctxt->error(ctxt->userData, "document has no root\n");
5315 return(ctxt->err);
5317 if (root->ns != NULL)
5318 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5319 root->name, root->ns->href, NULL);
5320 else
5321 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5322 root->name, NULL, NULL);
5323 if (elemDecl == NULL) {
5324 ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
5325 if (ctxt->error != NULL)
5326 ctxt->error(ctxt->userData, "Element %s not declared\n",
5327 root->name);
5328 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
5329 ctxt->err = XML_SCHEMAS_ERR_NOTTOPLEVEL;
5330 if (ctxt->error != NULL)
5331 ctxt->error(ctxt->userData, "Root element %s not toplevel\n",
5332 root->name);
5335 * Okay, start the recursive validation
5337 xmlSchemaValidateElement(ctxt, root);
5339 return(ctxt->err);
5342 /************************************************************************
5344 * SAX Validation code *
5346 ************************************************************************/
5348 /************************************************************************
5350 * Validation interfaces *
5352 ************************************************************************/
5355 * xmlSchemaNewValidCtxt:
5356 * @schema: a precompiled XML Schemas
5358 * Create an XML Schemas validation context based on the given schema
5360 * Returns the validation context or NULL in case of error
5362 xmlSchemaValidCtxtPtr
5363 xmlSchemaNewValidCtxt(xmlSchemaPtr schema) {
5364 xmlSchemaValidCtxtPtr ret;
5366 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
5367 if (ret == NULL) {
5368 xmlGenericError(xmlGenericErrorContext,
5369 "Failed to allocate new schama validation context\n");
5370 return (NULL);
5372 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
5373 ret->schema = schema;
5374 ret->attrNr = 0;
5375 ret->attrMax = 10;
5376 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
5377 sizeof(xmlSchemaAttrState));
5378 if (ret->attr == NULL) {
5379 free(ret);
5380 return(NULL);
5382 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
5383 return (ret);
5387 * xmlSchemaFreeValidCtxt:
5388 * @ctxt: the schema validation context
5390 * Free the resources associated to the schema validation context
5392 void
5393 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) {
5394 if (ctxt == NULL)
5395 return;
5396 if (ctxt->attr != NULL)
5397 xmlFree(ctxt->attr);
5398 if (ctxt->value != NULL)
5399 xmlSchemaFreeValue(ctxt->value);
5400 xmlFree(ctxt);
5404 * xmlSchemaSetValidErrors:
5405 * @ctxt: a schema validation context
5406 * @err: the error function
5407 * @warn: the warning function
5408 * @ctxt: the functions context
5410 * Set the error and warning callback informations
5412 void
5413 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
5414 xmlSchemaValidityErrorFunc err,
5415 xmlSchemaValidityWarningFunc warn, void *ctx) {
5416 if (ctxt == NULL)
5417 return;
5418 ctxt->error = err;
5419 ctxt->warning = warn;
5420 ctxt->userData = ctx;
5424 * xmlSchemaValidateDoc:
5425 * @ctxt: a schema validation context
5426 * @doc: a parsed document tree
5428 * Validate a document tree in memory.
5430 * Returns 0 if the document is schemas valid, a positive error code
5431 * number otherwise and -1 in case of internal or API error.
5434 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5435 int ret;
5437 if ((ctxt == NULL) || (doc == NULL))
5438 return(-1);
5440 ctxt->doc = doc;
5441 ret = xmlSchemaValidateDocument(ctxt, doc);
5442 return(ret);
5446 * xmlSchemaValidateStream:
5447 * @ctxt: a schema validation context
5448 * @input: the input to use for reading the data
5449 * @enc: an optional encoding information
5450 * @sax: a SAX handler for the resulting events
5451 * @user_data: the context to provide to the SAX handler.
5453 * Validate a document tree in memory.
5455 * Returns 0 if the document is schemas valid, a positive error code
5456 * number otherwise and -1 in case of internal or API error.
5458 int
5459 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
5460 xmlParserInputBufferPtr input, xmlCharEncoding enc,
5461 xmlSAXHandlerPtr sax, void *user_data) {
5462 if ((ctxt == NULL) || (input == NULL))
5463 return(-1);
5464 ctxt->input = input;
5465 ctxt->enc = enc;
5466 ctxt->sax = sax;
5467 ctxt->user_data = user_data;
5468 TODO
5469 return(0);
5472 #endif /* LIBXML_SCHEMAS_ENABLED */