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>
13 #ifdef LIBXML_SCHEMAS_ENABLED
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>
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)
36 xmlGenericError(xmlGenericErrorContext, \
37 "Unimplemented block at %s:%d\n", \
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;
65 xmlSchemaPtr schema; /* The schema in use */
66 xmlChar *container; /* the current element, group, ... */
76 * Used to build complex element content models
79 xmlAutomataStatePtr start;
80 xmlAutomataStatePtr end;
81 xmlAutomataStatePtr state;
85 #define XML_SCHEMAS_ATTR_UNKNOWN 1
86 #define XML_SCHEMAS_ATTR_CHECKED 2
88 typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
89 typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
90 struct _xmlSchemaAttrState {
98 * A Schemas validation context
101 struct _xmlSchemaValidCtxt {
102 void *userData; /* user specific data block */
103 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
104 xmlSchemaValidityWarningFunc warning;/* the callback in case of warning */
106 xmlSchemaPtr schema; /* The schema in use */
108 xmlParserInputBufferPtr input;
110 xmlSAXHandlerPtr sax;
119 xmlSchemaTypePtr type;
121 xmlRegExecCtxtPtr regexp;
122 xmlSchemaValPtr value;
127 xmlSchemaAttrStatePtr attr;
131 /************************************************************************
133 * Some predeclarations *
135 ************************************************************************/
136 static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
137 xmlSchemaTypePtr type,
140 /************************************************************************
142 * Allocation functions *
144 ************************************************************************/
147 * xmlSchemaNewSchema:
148 * @ctxt: a schema validation context (optional)
150 * Allocate a new Schema structure.
152 * Returns the newly allocated structure or NULL in case or error
155 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
159 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
162 if ((ctxt != NULL) && (ctxt->error != NULL))
163 ctxt->error(ctxt->userData, "Out of memory\n");
166 memset(ret, 0, sizeof(xmlSchema));
174 * Allocate a new Facet structure.
176 * Returns the newly allocated structure or NULL in case or error
179 xmlSchemaNewFacet(void)
181 xmlSchemaFacetPtr ret;
183 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
187 memset(ret, 0, sizeof(xmlSchemaFacet));
194 * @ctxt: a schema validation context (optional)
197 * Allocate a new annotation structure.
199 * Returns the newly allocated structure or NULL in case or error
201 static xmlSchemaAnnotPtr
202 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
204 xmlSchemaAnnotPtr ret;
206 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
209 if ((ctxt != NULL) && (ctxt->error != NULL))
210 ctxt->error(ctxt->userData, "Out of memory\n");
213 memset(ret, 0, sizeof(xmlSchemaAnnot));
219 * xmlSchemaFreeAnnot:
220 * @annot: a schema type structure
222 * Deallocate a annotation structure
225 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
233 * xmlSchemaFreeNotation:
234 * @schema: a schema notation structure
236 * Deallocate a Schema Notation structure.
239 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
243 if (nota->name != NULL)
244 xmlFree((xmlChar *) nota->name);
249 * xmlSchemaFreeAttribute:
250 * @schema: a schema attribute structure
252 * Deallocate a Schema Attribute structure.
255 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
259 if (attr->name != NULL)
260 xmlFree((xmlChar *) attr->name);
261 if (attr->ref != NULL)
262 xmlFree((xmlChar *) attr->ref);
263 if (attr->refNs != NULL)
264 xmlFree((xmlChar *) attr->refNs);
265 if (attr->typeName != NULL)
266 xmlFree((xmlChar *) attr->typeName);
267 if (attr->typeNs != NULL)
268 xmlFree((xmlChar *) attr->typeNs);
273 * xmlSchemaFreeAttributeGroup:
274 * @schema: a schema attribute group structure
276 * Deallocate a Schema Attribute Group structure.
279 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
283 if (attr->name != NULL)
284 xmlFree((xmlChar *) attr->name);
285 if (attr->ref != NULL)
286 xmlFree((xmlChar *) attr->ref);
287 if (attr->refNs != NULL)
288 xmlFree((xmlChar *) attr->refNs);
293 * xmlSchemaFreeElement:
294 * @schema: a schema element structure
296 * Deallocate a Schema Element structure.
299 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
303 if (elem->name != NULL)
304 xmlFree((xmlChar *) elem->name);
305 if (elem->namedType != NULL)
306 xmlFree((xmlChar *) elem->namedType);
307 if (elem->namedTypeNs != NULL)
308 xmlFree((xmlChar *) elem->namedTypeNs);
309 if (elem->ref != NULL)
310 xmlFree((xmlChar *) elem->ref);
311 if (elem->refNs != NULL)
312 xmlFree((xmlChar *) elem->refNs);
313 if (elem->annot != NULL)
314 xmlSchemaFreeAnnot(elem->annot);
315 if (elem->contModel != NULL)
316 xmlRegFreeRegexp(elem->contModel);
321 * xmlSchemaFreeFacet:
322 * @facet: a schema facet structure
324 * Deallocate a Schema Facet structure.
327 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
331 if (facet->value != NULL)
332 xmlFree((xmlChar *) facet->value);
333 if (facet->id != NULL)
334 xmlFree((xmlChar *) facet->id);
335 if (facet->val != NULL)
336 xmlSchemaFreeValue(facet->val);
337 if (facet->regexp != NULL)
338 xmlRegFreeRegexp(facet->regexp);
339 if (facet->annot != NULL)
340 xmlSchemaFreeAnnot(facet->annot);
346 * @type: a schema type structure
348 * Deallocate a Schema Type structure.
351 xmlSchemaFreeType(xmlSchemaTypePtr type)
355 if (type->name != NULL)
356 xmlFree((xmlChar *) type->name);
357 if (type->base != NULL)
358 xmlFree((xmlChar *) type->base);
359 if (type->baseNs != NULL)
360 xmlFree((xmlChar *) type->baseNs);
361 if (type->annot != NULL)
362 xmlSchemaFreeAnnot(type->annot);
363 if (type->facets != NULL) {
364 xmlSchemaFacetPtr facet, next;
366 facet = type->facets;
367 while (facet != NULL) {
369 xmlSchemaFreeFacet(facet);
378 * @schema: a schema structure
380 * Deallocate a Schema structure.
383 xmlSchemaFree(xmlSchemaPtr schema)
388 if (schema->id != NULL)
389 xmlFree((xmlChar *) schema->id);
390 if (schema->targetNamespace != NULL)
391 xmlFree((xmlChar *) schema->targetNamespace);
392 if (schema->name != NULL)
393 xmlFree((xmlChar *) schema->name);
394 if (schema->notaDecl != NULL)
395 xmlHashFree(schema->notaDecl,
396 (xmlHashDeallocator) xmlSchemaFreeNotation);
397 if (schema->attrDecl != NULL)
398 xmlHashFree(schema->attrDecl,
399 (xmlHashDeallocator) xmlSchemaFreeAttribute);
400 if (schema->attrgrpDecl != NULL)
401 xmlHashFree(schema->attrgrpDecl,
402 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
403 if (schema->elemDecl != NULL)
404 xmlHashFree(schema->elemDecl,
405 (xmlHashDeallocator) xmlSchemaFreeElement);
406 if (schema->typeDecl != NULL)
407 xmlHashFree(schema->typeDecl,
408 (xmlHashDeallocator) xmlSchemaFreeType);
409 if (schema->groupDecl != NULL)
410 xmlHashFree(schema->groupDecl,
411 (xmlHashDeallocator) xmlSchemaFreeType);
412 if (schema->annot != NULL)
413 xmlSchemaFreeAnnot(schema->annot);
414 if (schema->doc != NULL)
415 xmlFreeDoc(schema->doc);
420 /************************************************************************
424 ************************************************************************/
427 * xmlSchemaErrorContext:
428 * @ctxt: the parsing context
429 * @schema: the schema being built
430 * @node: the node being processed
431 * @child: the child being processed
433 * Dump a SchemaType structure
436 xmlSchemaErrorContext(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
437 xmlNodePtr node, xmlNodePtr child)
440 const xmlChar *file = NULL;
441 const xmlChar *name = NULL;
442 const xmlChar *prefix = NULL;
443 const char *type = "error";
445 if ((ctxt == NULL) || (ctxt->error == NULL))
452 if ((node->type == XML_DOCUMENT_NODE) ||
453 (node->type == XML_HTML_DOCUMENT_NODE)) {
454 xmlDocPtr doc = (xmlDocPtr) node;
459 * Try to find contextual informations to report
461 if (node->type == XML_ELEMENT_NODE) {
462 line = (long) node->content;
463 } else if ((node->prev != NULL) &&
464 (node->prev->type == XML_ELEMENT_NODE)) {
465 line = (long) node->prev->content;
466 } else if ((node->parent != NULL) &&
467 (node->parent->type == XML_ELEMENT_NODE)) {
468 line = (long) node->parent->content;
470 if ((node->doc != NULL) && (node->doc->URL != NULL))
471 file = node->doc->URL;
472 if (node->name != NULL)
474 if ((node->type == XML_ELEMENT_NODE) && (node->ns != NULL) &&
475 (node->ns->prefix != NULL))
476 prefix = node->ns->prefix;
481 type = "compilation error";
482 else if (schema != NULL)
483 type = "runtime error";
485 if ((file != NULL) && (line != 0) && (name != NULL) && (prefix != NULL))
486 ctxt->error(ctxt->userData, "%s: file %s line %d element %s:%s\n",
487 type, file, line, prefix, name);
488 else if ((file != NULL) && (line != 0) && (name != NULL))
489 ctxt->error(ctxt->userData, "%s: file %s line %d element %s\n",
490 type, file, line, name);
491 else if ((file != NULL) && (name != NULL) && (prefix != NULL))
492 ctxt->error(ctxt->userData, "%s: file %s element %s:%s\n",
493 type, file, prefix, name);
494 else if ((file != NULL) && (name != NULL))
495 ctxt->error(ctxt->userData, "%s: file %s element %s\n",
497 else if ((file != NULL) && (line != 0))
498 ctxt->error(ctxt->userData, "%s: file %s line %d\n", type, file, line);
499 else if (file != NULL)
500 ctxt->error(ctxt->userData, "%s: file %s\n", type, file);
501 else if ((name != NULL) && (prefix != NULL))
502 ctxt->error(ctxt->userData, "%s: element %s:%s\n", type, prefix, name);
503 else if (name != NULL)
504 ctxt->error(ctxt->userData, "%s: element %s\n", type, name);
506 ctxt->error(ctxt->userData, "%s\n", type);
509 /************************************************************************
513 ************************************************************************/
516 * xmlSchemaElementDump:
518 * @output: the file output
523 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
524 const xmlChar *name ATTRIBUTE_UNUSED,
525 const xmlChar *context ATTRIBUTE_UNUSED,
526 const xmlChar *namespace ATTRIBUTE_UNUSED)
531 fprintf(output, "Element ");
532 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
533 fprintf(output, "toplevel ");
534 fprintf(output, ": %s ", elem->name);
535 if (namespace != NULL)
536 fprintf(output, "namespace '%s' ", namespace);
538 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
539 fprintf(output, "nillable ");
540 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
541 fprintf(output, "global ");
542 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
543 fprintf(output, "default ");
544 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
545 fprintf(output, "fixed ");
546 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
547 fprintf(output, "abstract ");
548 if (elem->flags & XML_SCHEMAS_ELEM_REF)
549 fprintf(output, "ref '%s' ", elem->ref);
550 if (elem->id != NULL)
551 fprintf(output, "id '%s' ", elem->id);
552 fprintf(output, "\n");
553 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
554 fprintf(output, " ");
555 if (elem->minOccurs != 1)
556 fprintf(output, "min: %d ", elem->minOccurs);
557 if (elem->maxOccurs >= UNBOUNDED)
558 fprintf(output, "max: unbounded\n");
559 else if (elem->maxOccurs != 1)
560 fprintf(output, "max: %d\n", elem->maxOccurs);
562 fprintf(output, "\n");
564 if (elem->namedType != NULL) {
565 fprintf(output, " type: %s", elem->namedType);
566 if (elem->namedTypeNs != NULL)
567 fprintf(output, " ns %s\n", elem->namedTypeNs);
569 fprintf(output, "\n");
571 if (elem->substGroup != NULL) {
572 fprintf(output, " substitutionGroup: %s", elem->substGroup);
573 if (elem->substGroupNs != NULL)
574 fprintf(output, " ns %s\n", elem->substGroupNs);
576 fprintf(output, "\n");
578 if (elem->value != NULL)
579 fprintf(output, " default: %s", elem->value);
583 * xmlSchemaAnnotDump:
584 * @output: the file output
585 * @annot: a annotation
587 * Dump the annotation
590 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
597 content = xmlNodeGetContent(annot->content);
598 if (content != NULL) {
599 fprintf(output, " Annot: %s\n", content);
602 fprintf(output, " Annot: empty\n");
607 * @output: the file output
608 * @type: a type structure
610 * Dump a SchemaType structure
613 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
616 fprintf(output, "Type: NULL\n");
619 fprintf(output, "Type: ");
620 if (type->name != NULL)
621 fprintf(output, "%s, ", type->name);
623 fprintf(output, "no name");
624 switch (type->type) {
625 case XML_SCHEMA_TYPE_BASIC:
626 fprintf(output, "basic ");
628 case XML_SCHEMA_TYPE_SIMPLE:
629 fprintf(output, "simple ");
631 case XML_SCHEMA_TYPE_COMPLEX:
632 fprintf(output, "complex ");
634 case XML_SCHEMA_TYPE_SEQUENCE:
635 fprintf(output, "sequence ");
637 case XML_SCHEMA_TYPE_CHOICE:
638 fprintf(output, "choice ");
640 case XML_SCHEMA_TYPE_ALL:
641 fprintf(output, "all ");
643 case XML_SCHEMA_TYPE_UR:
644 fprintf(output, "ur ");
646 case XML_SCHEMA_TYPE_RESTRICTION:
647 fprintf(output, "restriction ");
649 case XML_SCHEMA_TYPE_EXTENSION:
650 fprintf(output, "extension ");
653 fprintf(output, "unknowntype%d ", type->type);
656 if (type->base != NULL) {
657 fprintf(output, "base %s, ", type->base);
659 switch (type->contentType) {
660 case XML_SCHEMA_CONTENT_UNKNOWN:
661 fprintf(output, "unknown ");
663 case XML_SCHEMA_CONTENT_EMPTY:
664 fprintf(output, "empty ");
666 case XML_SCHEMA_CONTENT_ELEMENTS:
667 fprintf(output, "element ");
669 case XML_SCHEMA_CONTENT_MIXED:
670 fprintf(output, "mixed ");
672 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
673 fprintf(output, "mixed_or_elems ");
675 case XML_SCHEMA_CONTENT_BASIC:
676 fprintf(output, "basic ");
678 case XML_SCHEMA_CONTENT_SIMPLE:
679 fprintf(output, "simple ");
681 case XML_SCHEMA_CONTENT_ANY:
682 fprintf(output, "any ");
685 fprintf(output, "\n");
686 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
687 fprintf(output, " ");
688 if (type->minOccurs != 1)
689 fprintf(output, "min: %d ", type->minOccurs);
690 if (type->maxOccurs >= UNBOUNDED)
691 fprintf(output, "max: unbounded\n");
692 else if (type->maxOccurs != 1)
693 fprintf(output, "max: %d\n", type->maxOccurs);
695 fprintf(output, "\n");
697 if (type->annot != NULL)
698 xmlSchemaAnnotDump(output, type->annot);
699 if (type->subtypes != NULL) {
700 xmlSchemaTypePtr sub = type->subtypes;
702 fprintf(output, " subtypes: ");
703 while (sub != NULL) {
704 fprintf(output, "%s ", sub->name);
707 fprintf(output, "\n");
714 * @output: the file output
715 * @schema: a schema structure
717 * Dump a Schema structure.
720 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
722 if (schema == NULL) {
723 fprintf(output, "Schemas: NULL\n");
726 fprintf(output, "Schemas: ");
727 if (schema->name != NULL)
728 fprintf(output, "%s, ", schema->name);
730 fprintf(output, "no name, ");
731 if (schema->targetNamespace != NULL)
732 fprintf(output, "%s", (const char *) schema->targetNamespace);
734 fprintf(output, "no target namespace");
735 fprintf(output, "\n");
736 if (schema->annot != NULL)
737 xmlSchemaAnnotDump(output, schema->annot);
739 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
741 xmlHashScanFull(schema->elemDecl,
742 (xmlHashScannerFull) xmlSchemaElementDump, output);
745 /************************************************************************
747 * Parsing functions *
749 ************************************************************************/
753 * @schema: the schemas context
754 * @name: the type name
755 * @ns: the type namespace
757 * Lookup a type in the schemas or the predefined types
759 * Returns the group definition or NULL if not found.
761 static xmlSchemaTypePtr
762 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
763 const xmlChar * namespace) {
764 xmlSchemaTypePtr ret;
768 if (schema != NULL) {
769 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
773 ret = xmlSchemaGetPredefinedType(name, namespace);
776 if (namespace == NULL)
777 fprintf(stderr, "Unable to lookup type %s", name);
779 fprintf(stderr, "Unable to lookup type %s:%s", name, namespace);
785 /************************************************************************
787 * Parsing functions *
789 ************************************************************************/
791 #define IS_BLANK_NODE(n) \
792 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
798 * Check if a string is ignorable
800 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
803 xmlSchemaIsBlank(xmlChar *str) {
807 if (!(IS_BLANK(*str))) return(0);
814 * xmlSchemaAddNotation:
815 * @ctxt: a schema validation context
816 * @schema: the schema being built
817 * @name: the item name
819 * Add an XML schema Attrribute declaration
820 * *WARNING* this interface is highly subject to change
822 * Returns the new struture or NULL in case of error
824 static xmlSchemaNotationPtr
825 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
826 const xmlChar * name)
828 xmlSchemaNotationPtr ret = NULL;
831 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
834 if (schema->notaDecl == NULL)
835 schema->notaDecl = xmlHashCreate(10);
836 if (schema->notaDecl == NULL)
839 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
842 if ((ctxt != NULL) && (ctxt->error != NULL))
843 ctxt->error(ctxt->userData, "Out of memory\n");
846 memset(ret, 0, sizeof(xmlSchemaNotation));
847 ret->name = xmlStrdup(name);
848 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
852 if ((ctxt != NULL) && (ctxt->error != NULL))
853 ctxt->error(ctxt->userData, "Notation %s already defined\n",
855 xmlFree((char *) ret->name);
864 * xmlSchemaAddAttribute:
865 * @ctxt: a schema validation context
866 * @schema: the schema being built
867 * @name: the item name
868 * @container: the container's name
870 * Add an XML schema Attrribute declaration
871 * *WARNING* this interface is highly subject to change
873 * Returns the new struture or NULL in case of error
875 static xmlSchemaAttributePtr
876 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
877 const xmlChar * name)
879 xmlSchemaAttributePtr ret = NULL;
882 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
885 if (schema->attrDecl == NULL)
886 schema->attrDecl = xmlHashCreate(10);
887 if (schema->attrDecl == NULL)
890 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
893 if ((ctxt != NULL) && (ctxt->error != NULL))
894 ctxt->error(ctxt->userData, "Out of memory\n");
897 memset(ret, 0, sizeof(xmlSchemaAttribute));
898 ret->name = xmlStrdup(name);
899 val = xmlHashAddEntry3(schema->attrDecl, name,
900 schema->targetNamespace, ctxt->container, ret);
903 if ((ctxt != NULL) && (ctxt->error != NULL))
904 ctxt->error(ctxt->userData, "Attribute %s already defined\n",
906 xmlFree((char *) ret->name);
914 * xmlSchemaAddAttributeGroup:
915 * @ctxt: a schema validation context
916 * @schema: the schema being built
917 * @name: the item name
919 * Add an XML schema Attrribute Group declaration
921 * Returns the new struture or NULL in case of error
923 static xmlSchemaAttributeGroupPtr
924 xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
925 const xmlChar * name)
927 xmlSchemaAttributeGroupPtr ret = NULL;
930 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
933 if (schema->attrgrpDecl == NULL)
934 schema->attrgrpDecl = xmlHashCreate(10);
935 if (schema->attrgrpDecl == NULL)
938 ret = (xmlSchemaAttributeGroupPtr) xmlMalloc(sizeof(xmlSchemaAttributeGroup));
941 if ((ctxt != NULL) && (ctxt->error != NULL))
942 ctxt->error(ctxt->userData, "Out of memory\n");
945 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
946 ret->name = xmlStrdup(name);
947 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
948 schema->targetNamespace, ctxt->container, ret);
951 if ((ctxt != NULL) && (ctxt->error != NULL))
952 ctxt->error(ctxt->userData, "Attribute group %s already defined\n",
954 xmlFree((char *) ret->name);
962 * xmlSchemaAddElement:
963 * @ctxt: a schema validation context
964 * @schema: the schema being built
965 * @name: the type name
966 * @namespace: the type namespace
968 * Add an XML schema Element declaration
969 * *WARNING* this interface is highly subject to change
971 * Returns the new struture or NULL in case of error
973 static xmlSchemaElementPtr
974 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
975 const xmlChar * name, const xmlChar * namespace)
977 xmlSchemaElementPtr ret = NULL;
980 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
983 if (schema->elemDecl == NULL)
984 schema->elemDecl = xmlHashCreate(10);
985 if (schema->elemDecl == NULL)
988 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
991 if ((ctxt != NULL) && (ctxt->error != NULL))
992 ctxt->error(ctxt->userData, "Out of memory\n");
995 memset(ret, 0, sizeof(xmlSchemaElement));
996 ret->name = xmlStrdup(name);
997 val = xmlHashAddEntry3(schema->elemDecl, name,
998 namespace, ctxt->container, ret);
1002 snprintf(buf, 99, "privatieelem%d", ctxt->counter++ + 1);
1003 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1007 if ((ctxt != NULL) && (ctxt->error != NULL))
1008 ctxt->error(ctxt->userData, "Element %s already defined\n",
1010 xmlFree((char *) ret->name);
1020 * @ctxt: a schema validation context
1021 * @schema: the schema being built
1022 * @name: the item name
1024 * Add an XML schema Simple Type definition
1025 * *WARNING* this interface is highly subject to change
1027 * Returns the new struture or NULL in case of error
1029 static xmlSchemaTypePtr
1030 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1031 const xmlChar * name)
1033 xmlSchemaTypePtr ret = NULL;
1036 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1039 if (schema->typeDecl == NULL)
1040 schema->typeDecl = xmlHashCreate(10);
1041 if (schema->typeDecl == NULL)
1044 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1047 if ((ctxt != NULL) && (ctxt->error != NULL))
1048 ctxt->error(ctxt->userData, "Out of memory\n");
1051 memset(ret, 0, sizeof(xmlSchemaType));
1052 ret->name = xmlStrdup(name);
1053 val = xmlHashAddEntry2(schema->typeDecl, name, schema->targetNamespace,
1057 if ((ctxt != NULL) && (ctxt->error != NULL))
1058 ctxt->error(ctxt->userData, "Type %s already defined\n", name);
1059 xmlFree((char *) ret->name);
1070 * xmlSchemaAddGroup:
1071 * @ctxt: a schema validation context
1072 * @schema: the schema being built
1073 * @name: the group name
1075 * Add an XML schema Group definition
1077 * Returns the new struture or NULL in case of error
1079 static xmlSchemaTypePtr
1080 xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1081 const xmlChar * name)
1083 xmlSchemaTypePtr ret = NULL;
1086 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1089 if (schema->groupDecl == NULL)
1090 schema->groupDecl = xmlHashCreate(10);
1091 if (schema->groupDecl == NULL)
1094 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1097 if ((ctxt != NULL) && (ctxt->error != NULL))
1098 ctxt->error(ctxt->userData, "Out of memory\n");
1101 memset(ret, 0, sizeof(xmlSchemaType));
1102 ret->name = xmlStrdup(name);
1103 val = xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1107 if ((ctxt != NULL) && (ctxt->error != NULL))
1108 ctxt->error(ctxt->userData, "Group %s already defined\n", name);
1109 xmlFree((char *) ret->name);
1119 /************************************************************************
1121 * Utilities for parsing *
1123 ************************************************************************/
1127 * @ctxt: a schema validation context
1128 * @node: a subtree containing XML Schema informations
1129 * @name: the attribute name
1130 * @namespace: the result namespace if any
1132 * Extract a QName Attribute value
1134 * Returns the NCName or NULL if not found, and also update @namespace
1135 * with the namespace URI
1138 xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1140 xmlChar **namespace) {
1141 xmlChar *val, *ret, *prefix;
1145 if (namespace != NULL)
1147 val = xmlGetProp(node, (const xmlChar *) name);
1151 ret = xmlSplitQName2(val, &prefix);
1156 ns = xmlSearchNs(node->doc, node, prefix);
1159 xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1160 if ((ctxt != NULL) && (ctxt->error != NULL))
1161 ctxt->error(ctxt->userData,
1162 "Attribute %s: the QName prefix %s is undefined\n",
1165 *namespace = xmlStrdup(ns->href);
1173 * @ctxt: a schema validation context
1174 * @node: a subtree containing XML Schema informations
1176 * Get the maxOccurs property
1178 * Returns the default if not found, or the value
1181 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) {
1185 val = xmlGetProp(node, (const xmlChar *) "maxOccurs");
1189 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
1191 return(UNBOUNDED); /* encoding it with -1 might be another option */
1195 while (IS_BLANK(*cur)) cur++;
1196 while ((*cur >= '0') && (*cur <= '9')) {
1197 ret = ret * 10 + (*cur - '0');
1200 while (IS_BLANK(*cur)) cur++;
1203 xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1204 if ((ctxt != NULL) && (ctxt->error != NULL))
1205 ctxt->error(ctxt->userData, "invalid value for minOccurs: %s\n",
1216 * @ctxt: a schema validation context
1217 * @node: a subtree containing XML Schema informations
1219 * Get the minOccurs property
1221 * Returns the default if not found, or the value
1224 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) {
1228 val = xmlGetProp(node, (const xmlChar *) "minOccurs");
1233 while (IS_BLANK(*cur)) cur++;
1234 while ((*cur >= '0') && (*cur <= '9')) {
1235 ret = ret * 10 + (*cur - '0');
1238 while (IS_BLANK(*cur)) cur++;
1241 xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1242 if ((ctxt != NULL) && (ctxt->error != NULL))
1243 ctxt->error(ctxt->userData, "invalid value for minOccurs: %s\n",
1253 * xmlGetBooleanProp:
1254 * @ctxt: a schema validation context
1255 * @node: a subtree containing XML Schema informations
1256 * @name: the attribute name
1257 * @def: the default value
1259 * Get is a bolean property is set
1261 * Returns the default if not found, 0 if found to be false,
1262 * 1 if found to be true
1265 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1266 const char *name, int def) {
1269 val = xmlGetProp(node, (const xmlChar *) name);
1273 if (xmlStrEqual(val, BAD_CAST"true"))
1275 else if (xmlStrEqual(val, BAD_CAST"false"))
1279 xmlSchemaErrorContext(ctxt, NULL, node, NULL);
1280 if ((ctxt != NULL) && (ctxt->error != NULL))
1281 ctxt->error(ctxt->userData,
1282 "Attribute %s: the value %s is not boolean\n",
1289 /************************************************************************
1291 * Shema extraction from an Infoset *
1293 ************************************************************************/
1294 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1295 ctxt, xmlSchemaPtr schema,
1297 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,
1298 xmlSchemaPtr schema,
1300 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,
1301 xmlSchemaPtr schema,
1304 static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1305 xmlSchemaPtr schema,
1307 static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1308 xmlSchemaPtr schema,
1310 static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1312 xmlSchemaPtr schema,
1314 static xmlSchemaAttributeGroupPtr
1315 xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1316 xmlSchemaPtr schema, xmlNodePtr node);
1317 static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1318 xmlSchemaPtr schema,
1320 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1321 xmlSchemaPtr schema,
1323 static xmlSchemaAttributePtr
1324 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1328 * xmlSchemaParseAttrDecls:
1329 * @ctxt: a schema validation context
1330 * @schema: the schema being built
1331 * @node: a subtree containing XML Schema informations
1332 * @type: the hosting type
1334 * parse a XML schema attrDecls declaration corresponding to
1335 * <!ENTITY % attrDecls
1336 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1339 xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1340 xmlNodePtr child, xmlSchemaTypePtr type)
1342 xmlSchemaAttributePtr lastattr, attr;
1345 while ((IS_SCHEMA(child, "attribute")) ||
1346 (IS_SCHEMA(child, "attributeGroup"))) {
1348 if (IS_SCHEMA(child, "attribute")) {
1349 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1350 } else if (IS_SCHEMA(child, "attributeGroup")) {
1351 attr = (xmlSchemaAttributePtr)
1352 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1355 if (lastattr == NULL) {
1356 type->attributes = attr;
1360 lastattr->next = attr;
1364 child = child->next;
1366 if (IS_SCHEMA(child, "anyAttribute")) {
1367 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1369 if (lastattr == NULL) {
1370 type->attributes = attr;
1374 lastattr->next = attr;
1378 child = child->next;
1384 * xmlSchemaParseAnnotation:
1385 * @ctxt: a schema validation context
1386 * @schema: the schema being built
1387 * @node: a subtree containing XML Schema informations
1389 * parse a XML schema Attrribute declaration
1390 * *WARNING* this interface is highly subject to change
1392 * Returns -1 in case of error, 0 if the declaration is inproper and
1393 * 1 in case of success.
1395 static xmlSchemaAnnotPtr
1396 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1399 xmlSchemaAnnotPtr ret;
1401 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1403 ret = xmlSchemaNewAnnot(ctxt, node);
1409 * xmlSchemaParseFacet:
1410 * @ctxt: a schema validation context
1411 * @schema: the schema being built
1412 * @node: a subtree containing XML Schema informations
1414 * parse a XML schema Facet declaration
1415 * *WARNING* this interface is highly subject to change
1417 * Returns the new type structure or NULL in case of error
1419 static xmlSchemaFacetPtr
1420 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1423 xmlSchemaFacetPtr facet;
1424 xmlNodePtr child = NULL;
1427 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1430 facet = xmlSchemaNewFacet();
1434 value = xmlGetProp(node, (const xmlChar *) "value");
1435 if (value == NULL) {
1437 xmlSchemaErrorContext(ctxt, schema, node, child);
1438 if ((ctxt != NULL) && (ctxt->error != NULL))
1439 ctxt->error(ctxt->userData, "Facet %s has no value\n", node->name);
1440 xmlSchemaFreeFacet(facet);
1443 if (IS_SCHEMA(node, "minInclusive")) {
1444 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
1445 } else if (IS_SCHEMA(node, "minExclusive")) {
1446 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
1447 } else if (IS_SCHEMA(node, "maxInclusive")) {
1448 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
1449 } else if (IS_SCHEMA(node, "maxExclusive")) {
1450 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
1451 } else if (IS_SCHEMA(node, "totalDigits")) {
1452 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
1453 } else if (IS_SCHEMA(node, "fractionDigits")) {
1454 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
1455 } else if (IS_SCHEMA(node, "pattern")) {
1456 facet->type = XML_SCHEMA_FACET_PATTERN;
1457 } else if (IS_SCHEMA(node, "enumeration")) {
1458 facet->type = XML_SCHEMA_FACET_ENUMERATION;
1459 } else if (IS_SCHEMA(node, "whiteSpace")) {
1460 facet->type = XML_SCHEMA_FACET_WHITESPACE;
1461 } else if (IS_SCHEMA(node, "length")) {
1462 facet->type = XML_SCHEMA_FACET_LENGTH;
1463 } else if (IS_SCHEMA(node, "maxLength")) {
1464 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1465 } else if (IS_SCHEMA(node, "minLength")) {
1466 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1469 xmlSchemaErrorContext(ctxt, schema, node, child);
1470 if ((ctxt != NULL) && (ctxt->error != NULL))
1471 ctxt->error(ctxt->userData, "Unknown facet type %s\n", node->name);
1472 xmlSchemaFreeFacet(facet);
1475 facet->id = xmlGetProp(node, (const xmlChar *) "id");
1476 facet->value = value;
1477 child = node->children;
1479 if (IS_SCHEMA(child, "annotation")) {
1480 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1481 child = child->next;
1483 if (child != NULL) {
1485 xmlSchemaErrorContext(ctxt, schema, node, child);
1486 if ((ctxt != NULL) && (ctxt->error != NULL))
1487 ctxt->error(ctxt->userData,
1488 "Facet %s has unexpected child content\n",
1495 * xmlSchemaParseAny:
1496 * @ctxt: a schema validation context
1497 * @schema: the schema being built
1498 * @node: a subtree containing XML Schema informations
1500 * parse a XML schema Any declaration
1501 * *WARNING* this interface is highly subject to change
1503 * Returns the new type structure or NULL in case of error
1505 static xmlSchemaTypePtr
1506 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1509 xmlSchemaTypePtr type;
1510 xmlNodePtr child = NULL;
1513 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1515 snprintf((char *)name, 30, "any %d", ctxt->counter++ + 1);
1516 type = xmlSchemaAddType(ctxt, schema, name);
1520 type->type = XML_SCHEMA_TYPE_ANY;
1521 child = node->children;
1522 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1523 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1525 if (IS_SCHEMA(child, "annotation")) {
1526 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1527 child = child->next;
1529 if (child != NULL) {
1531 xmlSchemaErrorContext(ctxt, schema, node, child);
1532 if ((ctxt != NULL) && (ctxt->error != NULL))
1533 ctxt->error(ctxt->userData,
1534 "Sequence %s has unexpected content\n",
1542 * xmlSchemaParseNotation:
1543 * @ctxt: a schema validation context
1544 * @schema: the schema being built
1545 * @node: a subtree containing XML Schema informations
1547 * parse a XML schema Notation declaration
1549 * Returns the new structure or NULL in case of error
1551 static xmlSchemaNotationPtr
1552 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1556 xmlSchemaNotationPtr ret;
1557 xmlNodePtr child = NULL;
1559 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1561 name = xmlGetProp(node, (const xmlChar *) "name");
1564 xmlSchemaErrorContext(ctxt, schema, node, child);
1565 if ((ctxt != NULL) && (ctxt->error != NULL))
1566 ctxt->error(ctxt->userData, "Notation has no name\n");
1569 ret = xmlSchemaAddNotation(ctxt, schema, name);
1574 child = node->children;
1575 if (IS_SCHEMA(child, "annotation")) {
1576 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1577 child = child->next;
1579 if (child != NULL) {
1581 xmlSchemaErrorContext(ctxt, schema, node, child);
1582 if ((ctxt != NULL) && (ctxt->error != NULL))
1583 ctxt->error(ctxt->userData,
1584 "notation %s has unexpected content\n",
1592 * xmlSchemaParseAnyAttribute:
1593 * @ctxt: a schema validation context
1594 * @schema: the schema being built
1595 * @node: a subtree containing XML Schema informations
1597 * parse a XML schema AnyAttrribute declaration
1598 * *WARNING* this interface is highly subject to change
1600 * Returns an attribute def structure or NULL
1602 static xmlSchemaAttributePtr
1603 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1606 xmlChar *processContents;
1607 xmlSchemaAttributePtr ret;
1608 xmlNodePtr child = NULL;
1611 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1614 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
1615 ret = xmlSchemaAddAttribute(ctxt, schema, (xmlChar *)name);
1619 ret->id = xmlGetProp(node, (const xmlChar *) "id");
1620 processContents = xmlGetProp(node, (const xmlChar *) "processContents");
1621 if ((processContents == NULL) ||
1622 (xmlStrEqual(processContents, (const xmlChar *)"strict"))) {
1623 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1624 } else if (xmlStrEqual(processContents, (const xmlChar *)"skip")) {
1625 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1626 } else if (xmlStrEqual(processContents, (const xmlChar *)"lax")) {
1627 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
1630 xmlSchemaErrorContext(ctxt, schema, node, child);
1631 if ((ctxt != NULL) && (ctxt->error != NULL))
1632 ctxt->error(ctxt->userData,
1633 "anyAttribute has unexpected content for processContents: %s\n",
1635 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1637 if (processContents != NULL)
1638 xmlFree(processContents);
1640 child = node->children;
1641 if (IS_SCHEMA(child, "annotation")) {
1642 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1643 child = child->next;
1645 if (child != NULL) {
1647 xmlSchemaErrorContext(ctxt, schema, node, child);
1648 if ((ctxt != NULL) && (ctxt->error != NULL))
1649 ctxt->error(ctxt->userData,
1650 "anyAttribute %s has unexpected content\n",
1659 * xmlSchemaParseAttribute:
1660 * @ctxt: a schema validation context
1661 * @schema: the schema being built
1662 * @node: a subtree containing XML Schema informations
1664 * parse a XML schema Attrribute declaration
1665 * *WARNING* this interface is highly subject to change
1667 * Returns -1 in case of error, 0 if the declaration is inproper and
1668 * 1 in case of success.
1670 static xmlSchemaAttributePtr
1671 xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1674 xmlChar *name, *refNs = NULL, *ref = NULL;
1675 xmlSchemaAttributePtr ret;
1676 xmlNodePtr child = NULL;
1678 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1680 name = xmlGetProp(node, (const xmlChar *) "name");
1684 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1687 xmlSchemaErrorContext(ctxt, schema, node, child);
1688 if ((ctxt != NULL) && (ctxt->error != NULL))
1689 ctxt->error(ctxt->userData, "Attribute has no name nor ref\n");
1692 snprintf(buf, 99, "anonattr%d", ctxt->counter++ + 1);
1693 name = xmlStrdup((xmlChar *) buf);
1695 ret = xmlSchemaAddAttribute(ctxt, schema, name);
1705 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
1707 child = node->children;
1708 if (IS_SCHEMA(child, "annotation")) {
1709 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1710 child = child->next;
1712 if (IS_SCHEMA(child, "simpleType")) {
1713 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1714 child = child->next;
1716 if (child != NULL) {
1718 xmlSchemaErrorContext(ctxt, schema, node, child);
1719 if ((ctxt != NULL) && (ctxt->error != NULL))
1720 ctxt->error(ctxt->userData,
1721 "attribute %s has unexpected content\n",
1729 * xmlSchemaParseAttributeGroup:
1730 * @ctxt: a schema validation context
1731 * @schema: the schema being built
1732 * @node: a subtree containing XML Schema informations
1734 * parse a XML schema Attribute Group declaration
1735 * *WARNING* this interface is highly subject to change
1737 * Returns the attribute group or NULL in case of error.
1739 static xmlSchemaAttributeGroupPtr
1740 xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1743 xmlChar *name, *refNs = NULL, *ref = NULL;
1744 xmlSchemaAttributeGroupPtr ret;
1745 xmlSchemaAttributePtr last = NULL, attr;
1746 xmlNodePtr child = NULL;
1747 xmlChar *oldcontainer;
1749 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1751 oldcontainer = ctxt->container;
1752 name = xmlGetProp(node, (const xmlChar *) "name");
1756 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1759 xmlSchemaErrorContext(ctxt, schema, node, child);
1760 if ((ctxt != NULL) && (ctxt->error != NULL))
1761 ctxt->error(ctxt->userData,
1762 "AttributeGroup has no name nor ref\n");
1765 snprintf(buf, 99, "anonattrgroup%d", ctxt->counter++ + 1);
1766 name = xmlStrdup((xmlChar *) buf);
1769 if ((ctxt != NULL) && (ctxt->error != NULL))
1770 ctxt->error(ctxt->userData,
1775 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
1784 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
1786 child = node->children;
1787 ctxt->container = name;
1788 if (IS_SCHEMA(child, "annotation")) {
1789 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1790 child = child->next;
1792 while ((IS_SCHEMA(child, "attribute")) ||
1793 (IS_SCHEMA(child, "attributeGroup"))) {
1795 if (IS_SCHEMA(child, "attribute")) {
1796 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1797 } else if (IS_SCHEMA(child, "attributeGroup")) {
1798 attr = (xmlSchemaAttributePtr)
1799 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1803 ret->attributes = attr;
1810 child = child->next;
1812 if (IS_SCHEMA(child, "anyAttribute")) {
1814 child = child->next;
1816 if (child != NULL) {
1818 xmlSchemaErrorContext(ctxt, schema, node, child);
1819 if ((ctxt != NULL) && (ctxt->error != NULL))
1820 ctxt->error(ctxt->userData,
1821 "attribute group %s has unexpected content\n",
1825 ctxt->container = oldcontainer;
1831 * xmlSchemaParseElement:
1832 * @ctxt: a schema validation context
1833 * @schema: the schema being built
1834 * @node: a subtree containing XML Schema informations
1836 * parse a XML schema Element declaration
1837 * *WARNING* this interface is highly subject to change
1839 * Returns -1 in case of error, 0 if the declaration is inproper and
1840 * 1 in case of success.
1842 static xmlSchemaElementPtr
1843 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1844 xmlNodePtr node, int toplevel)
1846 xmlChar *name, *refNs = NULL, *ref = NULL, *namespace, *fixed;
1847 xmlSchemaElementPtr ret;
1848 xmlNodePtr child = NULL;
1849 xmlChar *oldcontainer;
1851 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1853 oldcontainer = ctxt->container;
1854 name = xmlGetProp(node, (const xmlChar *) "name");
1858 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
1861 xmlSchemaErrorContext(ctxt, schema, node, child);
1862 if ((ctxt != NULL) && (ctxt->error != NULL))
1863 ctxt->error(ctxt->userData, "Element has no name nor ref\n");
1866 snprintf(buf, 99, "anonelem%d", ctxt->counter++ + 1);
1867 name = xmlStrdup((xmlChar *) buf);
1869 namespace = xmlGetProp(node, (const xmlChar *) "targetNamespace");
1870 if (namespace == NULL)
1872 xmlSchemaAddElement(ctxt, schema, name,
1873 schema->targetNamespace);
1875 ret = xmlSchemaAddElement(ctxt, schema, name, namespace);
1877 if (namespace != NULL)
1885 ret->type = XML_SCHEMA_TYPE_ELEMENT;
1889 ret->flags |= XML_SCHEMAS_ELEM_REF;
1891 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
1892 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
1893 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1894 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
1895 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
1896 ctxt->container = name;
1898 ret->id = xmlGetProp(node, BAD_CAST "id");
1899 ret->namedType = xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
1900 ret->substGroup = xmlGetQNameProp(ctxt, node, "substitutionGroup",
1901 &(ret->substGroupNs));
1902 fixed = xmlGetProp(node, BAD_CAST "fixed");
1903 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
1904 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1906 ret->value = xmlGetProp(node, BAD_CAST "default");
1907 if ((ret->value != NULL) && (fixed != NULL)) {
1909 xmlSchemaErrorContext(ctxt, schema, node, child);
1910 ctxt->error(ctxt->userData,
1911 "Element %s has both default and fixed\n",
1914 } else if (fixed != NULL) {
1915 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
1919 child = node->children;
1920 if (IS_SCHEMA(child, "annotation")) {
1921 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1922 child = child->next;
1924 if (IS_SCHEMA(child, "complexType")) {
1925 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
1926 child = child->next;
1927 } else if (IS_SCHEMA(child, "simpleType")) {
1928 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
1929 child = child->next;
1931 while ((IS_SCHEMA(child, "unique")) ||
1932 (IS_SCHEMA(child, "key")) ||
1933 (IS_SCHEMA(child, "keyref"))) {
1935 child = child->next;
1937 if (child != NULL) {
1939 xmlSchemaErrorContext(ctxt, schema, node, child);
1940 if ((ctxt != NULL) && (ctxt->error != NULL))
1941 ctxt->error(ctxt->userData,
1942 "element %s has unexpected content\n",
1946 ctxt->container = oldcontainer;
1952 * xmlSchemaParseUnion:
1953 * @ctxt: a schema validation context
1954 * @schema: the schema being built
1955 * @node: a subtree containing XML Schema informations
1957 * parse a XML schema Union definition
1958 * *WARNING* this interface is highly subject to change
1960 * Returns -1 in case of error, 0 if the declaration is inproper and
1961 * 1 in case of success.
1963 static xmlSchemaTypePtr
1964 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1967 xmlSchemaTypePtr type, subtype, last = NULL;
1968 xmlNodePtr child = NULL;
1971 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1975 snprintf((char *)name, 30, "union %d", ctxt->counter++ + 1);
1976 type = xmlSchemaAddType(ctxt, schema, name);
1980 type->type = XML_SCHEMA_TYPE_LIST;
1981 type->id = xmlGetProp(node, BAD_CAST "id");
1982 type->ref = xmlGetProp(node, BAD_CAST "memberTypes");
1984 child = node->children;
1985 if (IS_SCHEMA(child, "annotation")) {
1986 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1987 child = child->next;
1989 while (IS_SCHEMA(child, "simpleType")) {
1990 subtype = (xmlSchemaTypePtr)
1991 xmlSchemaParseSimpleType(ctxt, schema, child);
1992 if (subtype != NULL) {
1994 type->subtypes = subtype;
1997 last->next = subtype;
2002 child = child->next;
2004 if (child != NULL) {
2006 xmlSchemaErrorContext(ctxt, schema, node, child);
2007 if ((ctxt != NULL) && (ctxt->error != NULL))
2008 ctxt->error(ctxt->userData,
2009 "Union %s has unexpected content\n",
2016 * xmlSchemaParseList:
2017 * @ctxt: a schema validation context
2018 * @schema: the schema being built
2019 * @node: a subtree containing XML Schema informations
2021 * parse a XML schema List definition
2022 * *WARNING* this interface is highly subject to change
2024 * Returns -1 in case of error, 0 if the declaration is inproper and
2025 * 1 in case of success.
2027 static xmlSchemaTypePtr
2028 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2031 xmlSchemaTypePtr type, subtype;
2032 xmlNodePtr child = NULL;
2035 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2038 snprintf((char *)name, 30, "list %d", ctxt->counter++ + 1);
2039 type = xmlSchemaAddType(ctxt, schema, name);
2043 type->type = XML_SCHEMA_TYPE_LIST;
2044 type->id = xmlGetProp(node, BAD_CAST "id");
2045 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2047 child = node->children;
2048 if (IS_SCHEMA(child, "annotation")) {
2049 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2050 child = child->next;
2053 if (IS_SCHEMA(child, "simpleType")) {
2054 subtype = (xmlSchemaTypePtr)
2055 xmlSchemaParseSimpleType(ctxt, schema, child);
2056 child = child->next;
2057 type->subtypes = subtype;
2059 if (child != NULL) {
2061 xmlSchemaErrorContext(ctxt, schema, node, child);
2062 if ((ctxt != NULL) && (ctxt->error != NULL))
2063 ctxt->error(ctxt->userData,
2064 "List %s has unexpected content\n",
2070 * xmlSchemaParseSimpleType:
2071 * @ctxt: a schema validation context
2072 * @schema: the schema being built
2073 * @node: a subtree containing XML Schema informations
2075 * parse a XML schema Simple Type definition
2076 * *WARNING* this interface is highly subject to change
2078 * Returns -1 in case of error, 0 if the declaration is inproper and
2079 * 1 in case of success.
2081 static xmlSchemaTypePtr
2082 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2085 xmlSchemaTypePtr type, subtype;
2086 xmlNodePtr child = NULL;
2089 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2093 name = xmlGetProp(node, (const xmlChar *) "name");
2097 snprintf(buf, 99, "simpletype%d", ctxt->counter++ + 1);
2098 name = xmlStrdup((xmlChar *) buf);
2102 xmlSchemaErrorContext(ctxt, schema, node, child);
2103 if ((ctxt != NULL) && (ctxt->error != NULL))
2104 ctxt->error(ctxt->userData, "simpleType has no name\n");
2107 type = xmlSchemaAddType(ctxt, schema, name);
2112 type->type = XML_SCHEMA_TYPE_SIMPLE;
2113 type->id = xmlGetProp(node, BAD_CAST "id");
2115 child = node->children;
2116 if (IS_SCHEMA(child, "annotation")) {
2117 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2118 child = child->next;
2121 if (IS_SCHEMA(child, "restriction")) {
2122 subtype = (xmlSchemaTypePtr)
2123 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2124 child = child->next;
2125 } else if (IS_SCHEMA(child, "list")) {
2126 subtype = (xmlSchemaTypePtr)
2127 xmlSchemaParseList(ctxt, schema, child);
2128 child = child->next;
2129 } else if (IS_SCHEMA(child, "union")) {
2130 subtype = (xmlSchemaTypePtr)
2131 xmlSchemaParseUnion(ctxt, schema, child);
2132 child = child->next;
2134 type->subtypes = subtype;
2135 if (child != NULL) {
2137 xmlSchemaErrorContext(ctxt, schema, node, child);
2138 if ((ctxt != NULL) && (ctxt->error != NULL))
2139 ctxt->error(ctxt->userData,
2140 "SimpleType %s has unexpected content\n",
2149 * xmlSchemaParseGroup:
2150 * @ctxt: a schema validation context
2151 * @schema: the schema being built
2152 * @node: a subtree containing XML Schema informations
2154 * parse a XML schema Group definition
2155 * *WARNING* this interface is highly subject to change
2157 * Returns -1 in case of error, 0 if the declaration is inproper and
2158 * 1 in case of success.
2160 static xmlSchemaTypePtr
2161 xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2164 xmlSchemaTypePtr type, subtype;
2165 xmlNodePtr child = NULL;
2166 xmlChar *name, *ref = NULL, *refNs = NULL;
2168 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2172 name = xmlGetProp(node, (const xmlChar *) "name");
2176 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2179 xmlSchemaErrorContext(ctxt, schema, node, child);
2180 if ((ctxt != NULL) && (ctxt->error != NULL))
2181 ctxt->error(ctxt->userData, "Group has no name nor ref\n");
2184 snprintf(buf, 99, "anongroup%d", ctxt->counter++ + 1);
2185 name = xmlStrdup((xmlChar *) buf);
2187 type = xmlSchemaAddGroup(ctxt, schema, name);
2191 type->type = XML_SCHEMA_TYPE_GROUP;
2192 type->id = xmlGetProp(node, BAD_CAST "id");
2194 type->refNs = refNs;
2195 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2196 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2198 child = node->children;
2199 if (IS_SCHEMA(child, "annotation")) {
2200 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2201 child = child->next;
2204 if (IS_SCHEMA(child, "all")) {
2205 subtype = (xmlSchemaTypePtr)
2206 xmlSchemaParseAll(ctxt, schema, child);
2207 child = child->next;
2208 } else if (IS_SCHEMA(child, "choice")) {
2209 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2210 child = child->next;
2211 } else if (IS_SCHEMA(child, "sequence")) {
2212 subtype = (xmlSchemaTypePtr)
2213 xmlSchemaParseSequence(ctxt, schema, child);
2214 child = child->next;
2216 if (subtype != NULL)
2217 type->subtypes = subtype;
2218 if (child != NULL) {
2220 xmlSchemaErrorContext(ctxt, schema, node, child);
2221 if ((ctxt != NULL) && (ctxt->error != NULL))
2222 ctxt->error(ctxt->userData,
2223 "Group %s has unexpected content\n",
2231 * xmlSchemaParseAll:
2232 * @ctxt: a schema validation context
2233 * @schema: the schema being built
2234 * @node: a subtree containing XML Schema informations
2236 * parse a XML schema All definition
2237 * *WARNING* this interface is highly subject to change
2239 * Returns -1 in case of error, 0 if the declaration is inproper and
2240 * 1 in case of success.
2242 static xmlSchemaTypePtr
2243 xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2246 xmlSchemaTypePtr type, subtype, last = NULL;
2247 xmlNodePtr child = NULL;
2250 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2254 snprintf((char *)name, 30, "all%d", ctxt->counter++ + 1);
2255 type = xmlSchemaAddType(ctxt, schema, name);
2259 type->type = XML_SCHEMA_TYPE_ALL;
2260 type->id = xmlGetProp(node, BAD_CAST "id");
2261 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2262 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2264 child = node->children;
2265 if (IS_SCHEMA(child, "annotation")) {
2266 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2267 child = child->next;
2269 while (IS_SCHEMA(child, "element")) {
2270 subtype = (xmlSchemaTypePtr)
2271 xmlSchemaParseElement(ctxt, schema, child, 0);
2272 if (subtype != NULL) {
2274 type->subtypes = subtype;
2277 last->next = subtype;
2282 child = child->next;
2284 if (child != NULL) {
2286 xmlSchemaErrorContext(ctxt, schema, node, child);
2287 if ((ctxt != NULL) && (ctxt->error != NULL))
2288 ctxt->error(ctxt->userData,
2289 "All %s has unexpected content\n",
2297 * xmlSchemaParseImport:
2298 * @ctxt: a schema validation context
2299 * @schema: the schema being built
2300 * @node: a subtree containing XML Schema informations
2302 * parse a XML schema Import definition
2303 * *WARNING* this interface is highly subject to change
2305 * Returns -1 in case of error, 0 if the declaration is inproper and
2306 * 1 in case of success.
2309 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2312 xmlNodePtr child = NULL;
2314 xmlChar *schemaLocation;
2318 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2321 namespace = xmlGetProp(node, BAD_CAST "namespace");
2322 if (namespace != NULL) {
2323 check = xmlParseURI((const char *) namespace);
2324 if (check == NULL) {
2326 xmlSchemaErrorContext(ctxt, schema, node, child);
2327 if ((ctxt != NULL) && (ctxt->error != NULL))
2328 ctxt->error(ctxt->userData,
2329 "Import namespace attribute is not an URI: %s\n",
2337 schemaLocation = xmlGetProp(node, BAD_CAST "schemaLocation");
2338 if (schemaLocation != NULL) {
2339 check = xmlParseURI((const char *) schemaLocation);
2340 if (check == NULL) {
2342 xmlSchemaErrorContext(ctxt, schema, node, child);
2343 if ((ctxt != NULL) && (ctxt->error != NULL))
2344 ctxt->error(ctxt->userData,
2345 "Import schemaLocation attribute is not an URI: %s\n",
2347 if (namespace != NULL)
2349 xmlFree(schemaLocation);
2355 if (schema->schemasImports == NULL) {
2356 schema->schemasImports = xmlHashCreate(10);
2357 if (schema->schemasImports == NULL) {
2359 xmlSchemaErrorContext(ctxt, schema, node, child);
2360 if ((ctxt != NULL) && (ctxt->error != NULL))
2361 ctxt->error(ctxt->userData,
2362 "Internal: failed to build import table\n");
2363 if (namespace != NULL)
2365 if (schemaLocation != NULL)
2366 xmlFree(schemaLocation);
2370 if (namespace == NULL) {
2371 previous = xmlHashLookup(schema->schemasImports,
2372 XML_SCHEMAS_DEFAULT_NAMESPACE);
2373 if (schemaLocation != NULL) {
2374 if (previous != NULL) {
2375 if (!xmlStrEqual(schemaLocation, previous)) {
2377 xmlSchemaErrorContext(ctxt, schema, node, child);
2378 if ((ctxt != NULL) && (ctxt->error != NULL))
2379 ctxt->error(ctxt->userData,
2380 "Redefining import for default namespace with a different URI: %s\n",
2384 xmlHashAddEntry(schema->schemasImports,
2385 XML_SCHEMAS_DEFAULT_NAMESPACE, schemaLocation);
2389 previous = xmlHashLookup(schema->schemasImports, namespace);
2390 if (schemaLocation != NULL) {
2391 if (previous != NULL) {
2392 if (!xmlStrEqual(schemaLocation, previous)) {
2394 xmlSchemaErrorContext(ctxt, schema, node, child);
2395 if ((ctxt != NULL) && (ctxt->error != NULL))
2396 ctxt->error(ctxt->userData,
2397 "Redefining import for namespace %s with a different URI: %s\n",
2398 namespace, schemaLocation);
2401 xmlHashAddEntry(schema->schemasImports,
2402 namespace, schemaLocation);
2407 child = node->children;
2408 while (IS_SCHEMA(child, "annotation")) {
2410 * the annotations here are simply discarded ...
2412 child = child->next;
2414 if (child != NULL) {
2416 xmlSchemaErrorContext(ctxt, schema, node, child);
2417 if ((ctxt != NULL) && (ctxt->error != NULL))
2418 ctxt->error(ctxt->userData,
2419 "Import has unexpected content\n");
2426 * xmlSchemaParseChoice:
2427 * @ctxt: a schema validation context
2428 * @schema: the schema being built
2429 * @node: a subtree containing XML Schema informations
2431 * parse a XML schema Choice definition
2432 * *WARNING* this interface is highly subject to change
2434 * Returns -1 in case of error, 0 if the declaration is inproper and
2435 * 1 in case of success.
2437 static xmlSchemaTypePtr
2438 xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2441 xmlSchemaTypePtr type, subtype, last = NULL;
2442 xmlNodePtr child = NULL;
2445 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2449 snprintf((char *)name, 30, "choice %d", ctxt->counter++ + 1);
2450 type = xmlSchemaAddType(ctxt, schema, name);
2454 type->type = XML_SCHEMA_TYPE_CHOICE;
2455 type->id = xmlGetProp(node, BAD_CAST "id");
2456 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2457 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2459 child = node->children;
2460 if (IS_SCHEMA(child, "annotation")) {
2461 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2462 child = child->next;
2464 while ((IS_SCHEMA(child, "element")) ||
2465 (IS_SCHEMA(child, "group")) ||
2466 (IS_SCHEMA(child, "any")) ||
2467 (IS_SCHEMA(child, "choice")) ||
2468 (IS_SCHEMA(child, "sequence"))) {
2470 if (IS_SCHEMA(child, "element")) {
2471 subtype = (xmlSchemaTypePtr)
2472 xmlSchemaParseElement(ctxt, schema, child, 0);
2473 } else if (IS_SCHEMA(child, "group")) {
2474 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2475 } else if (IS_SCHEMA(child, "any")) {
2476 subtype = xmlSchemaParseAny(ctxt, schema, child);
2477 } else if (IS_SCHEMA(child, "sequence")) {
2478 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2479 } else if (IS_SCHEMA(child, "choice")) {
2480 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2482 if (subtype != NULL) {
2484 type->subtypes = subtype;
2487 last->next = subtype;
2492 child = child->next;
2494 if (child != NULL) {
2496 xmlSchemaErrorContext(ctxt, schema, node, child);
2497 if ((ctxt != NULL) && (ctxt->error != NULL))
2498 ctxt->error(ctxt->userData,
2499 "Choice %s has unexpected content\n",
2507 * xmlSchemaParseSequence:
2508 * @ctxt: a schema validation context
2509 * @schema: the schema being built
2510 * @node: a subtree containing XML Schema informations
2512 * parse a XML schema Sequence definition
2513 * *WARNING* this interface is highly subject to change
2515 * Returns -1 in case of error, 0 if the declaration is inproper and
2516 * 1 in case of success.
2518 static xmlSchemaTypePtr
2519 xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2522 xmlSchemaTypePtr type, subtype, last = NULL;
2523 xmlNodePtr child = NULL;
2526 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2530 snprintf((char *)name, 30, "sequence %d", ctxt->counter++ + 1);
2531 type = xmlSchemaAddType(ctxt, schema, name);
2535 type->type = XML_SCHEMA_TYPE_SEQUENCE;
2536 type->id = xmlGetProp(node, BAD_CAST "id");
2537 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2538 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2540 child = node->children;
2541 if (IS_SCHEMA(child, "annotation")) {
2542 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2543 child = child->next;
2545 while ((IS_SCHEMA(child, "element")) ||
2546 (IS_SCHEMA(child, "group")) ||
2547 (IS_SCHEMA(child, "any")) ||
2548 (IS_SCHEMA(child, "choice")) ||
2549 (IS_SCHEMA(child, "sequence"))) {
2551 if (IS_SCHEMA(child, "element")) {
2552 subtype = (xmlSchemaTypePtr)
2553 xmlSchemaParseElement(ctxt, schema, child, 0);
2554 } else if (IS_SCHEMA(child, "group")) {
2555 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2556 } else if (IS_SCHEMA(child, "any")) {
2557 subtype = xmlSchemaParseAny(ctxt, schema, child);
2558 } else if (IS_SCHEMA(child, "choice")) {
2559 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2560 } else if (IS_SCHEMA(child, "sequence")) {
2561 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2563 if (subtype != NULL) {
2565 type->subtypes = subtype;
2568 last->next = subtype;
2573 child = child->next;
2575 if (child != NULL) {
2577 xmlSchemaErrorContext(ctxt, schema, node, child);
2578 if ((ctxt != NULL) && (ctxt->error != NULL))
2579 ctxt->error(ctxt->userData,
2580 "Sequence %s has unexpected content\n",
2588 * xmlSchemaParseRestriction:
2589 * @ctxt: a schema validation context
2590 * @schema: the schema being built
2591 * @node: a subtree containing XML Schema informations
2592 * @simple: is that part of a simple type.
2594 * parse a XML schema Restriction definition
2595 * *WARNING* this interface is highly subject to change
2597 * Returns the type definition or NULL in case of error
2599 static xmlSchemaTypePtr
2600 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2601 xmlNodePtr node, int simple)
2603 xmlSchemaTypePtr type, subtype;
2604 xmlSchemaFacetPtr facet, lastfacet = NULL;
2605 xmlNodePtr child = NULL;
2607 xmlChar *oldcontainer;
2609 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2612 oldcontainer = ctxt->container;
2614 snprintf((char *)name, 30, "restriction %d", ctxt->counter++ + 1);
2615 type = xmlSchemaAddType(ctxt, schema, name);
2619 type->type = XML_SCHEMA_TYPE_RESTRICTION;
2620 type->id = xmlGetProp(node, BAD_CAST "id");
2621 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2622 if ((!simple) && (type->base == NULL)) {
2624 xmlSchemaErrorContext(ctxt, schema, node, child);
2625 if ((ctxt != NULL) && (ctxt->error != NULL))
2626 ctxt->error(ctxt->userData,
2627 "Restriction %s has no base\n",
2630 ctxt->container = name;
2632 child = node->children;
2633 if (IS_SCHEMA(child, "annotation")) {
2634 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2635 child = child->next;
2639 if (IS_SCHEMA(child, "all")) {
2640 subtype = (xmlSchemaTypePtr)
2641 xmlSchemaParseAll(ctxt, schema, child);
2642 child = child->next;
2643 type->subtypes = subtype;
2644 } else if (IS_SCHEMA(child, "choice")) {
2645 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2646 child = child->next;
2647 type->subtypes = subtype;
2648 } else if (IS_SCHEMA(child, "sequence")) {
2649 subtype = (xmlSchemaTypePtr)
2650 xmlSchemaParseSequence(ctxt, schema, child);
2651 child = child->next;
2652 type->subtypes = subtype;
2653 } else if (IS_SCHEMA(child, "group")) {
2654 subtype = (xmlSchemaTypePtr)
2655 xmlSchemaParseGroup(ctxt, schema, child);
2656 child = child->next;
2657 type->subtypes = subtype;
2659 if (IS_SCHEMA(child, "simpleType")) {
2660 subtype = (xmlSchemaTypePtr)
2661 xmlSchemaParseSimpleType(ctxt, schema, child);
2662 child = child->next;
2663 type->baseType = subtype;
2668 while ((IS_SCHEMA(child, "minInclusive")) ||
2669 (IS_SCHEMA(child, "minExclusive")) ||
2670 (IS_SCHEMA(child, "maxInclusive")) ||
2671 (IS_SCHEMA(child, "maxExclusive")) ||
2672 (IS_SCHEMA(child, "totalDigits")) ||
2673 (IS_SCHEMA(child, "fractionDigits")) ||
2674 (IS_SCHEMA(child, "pattern")) ||
2675 (IS_SCHEMA(child, "enumeration")) ||
2676 (IS_SCHEMA(child, "whiteSpace")) ||
2677 (IS_SCHEMA(child, "length")) ||
2678 (IS_SCHEMA(child, "maxLength")) ||
2679 (IS_SCHEMA(child, "minLength"))) {
2680 facet = xmlSchemaParseFacet(ctxt, schema, child);
2681 if (facet != NULL) {
2682 if (lastfacet == NULL) {
2683 type->facets = facet;
2686 lastfacet->next = facet;
2689 lastfacet->next = NULL;
2691 child = child->next;
2694 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2695 if (child != NULL) {
2697 xmlSchemaErrorContext(ctxt, schema, node, child);
2698 if ((ctxt != NULL) && (ctxt->error != NULL))
2699 ctxt->error(ctxt->userData,
2700 "Restriction %s has unexpected content\n",
2703 ctxt->container = oldcontainer;
2708 * xmlSchemaParseExtension:
2709 * @ctxt: a schema validation context
2710 * @schema: the schema being built
2711 * @node: a subtree containing XML Schema informations
2713 * parse a XML schema Extension definition
2714 * *WARNING* this interface is highly subject to change
2716 * Returns the type definition or NULL in case of error
2718 static xmlSchemaTypePtr
2719 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2722 xmlSchemaTypePtr type, subtype;
2723 xmlNodePtr child = NULL;
2725 xmlChar *oldcontainer;
2727 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2730 oldcontainer = ctxt->container;
2732 snprintf((char *)name, 30, "extension %d", ctxt->counter++ + 1);
2733 type = xmlSchemaAddType(ctxt, schema, name);
2737 type->type = XML_SCHEMA_TYPE_EXTENSION;
2738 type->id = xmlGetProp(node, BAD_CAST "id");
2739 ctxt->container = name;
2741 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2742 if (type->base == NULL) {
2744 xmlSchemaErrorContext(ctxt, schema, node, child);
2745 if ((ctxt != NULL) && (ctxt->error != NULL))
2746 ctxt->error(ctxt->userData,
2747 "Extension %s has no base\n",
2750 child = node->children;
2751 if (IS_SCHEMA(child, "annotation")) {
2752 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2753 child = child->next;
2757 if (IS_SCHEMA(child, "all")) {
2758 subtype = xmlSchemaParseAll(ctxt, schema, child);
2759 child = child->next;
2760 } else if (IS_SCHEMA(child, "choice")) {
2761 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2762 child = child->next;
2763 } else if (IS_SCHEMA(child, "sequence")) {
2764 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2765 child = child->next;
2766 } else if (IS_SCHEMA(child, "group")) {
2767 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2768 child = child->next;
2770 if (subtype != NULL)
2771 type->subtypes = subtype;
2772 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2773 if (child != NULL) {
2775 xmlSchemaErrorContext(ctxt, schema, node, child);
2776 if ((ctxt != NULL) && (ctxt->error != NULL))
2777 ctxt->error(ctxt->userData,
2778 "Extension %s has unexpected content\n",
2781 ctxt->container = oldcontainer;
2786 * xmlSchemaParseSimpleContent:
2787 * @ctxt: a schema validation context
2788 * @schema: the schema being built
2789 * @node: a subtree containing XML Schema informations
2791 * parse a XML schema SimpleContent definition
2792 * *WARNING* this interface is highly subject to change
2794 * Returns the type definition or NULL in case of error
2796 static xmlSchemaTypePtr
2797 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2800 xmlSchemaTypePtr type, subtype;
2801 xmlNodePtr child = NULL;
2804 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2808 snprintf((char *)name, 30, "complexContent %d", ctxt->counter++ + 1);
2809 type = xmlSchemaAddType(ctxt, schema, name);
2813 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
2814 type->id = xmlGetProp(node, BAD_CAST "id");
2816 child = node->children;
2817 if (IS_SCHEMA(child, "annotation")) {
2818 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2819 child = child->next;
2822 if (IS_SCHEMA(child, "restriction")) {
2823 subtype = (xmlSchemaTypePtr)
2824 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2825 child = child->next;
2826 } else if (IS_SCHEMA(child, "extension")) {
2827 subtype = (xmlSchemaTypePtr)
2828 xmlSchemaParseExtension(ctxt, schema, child);
2829 child = child->next;
2831 type->subtypes = subtype;
2832 if (child != NULL) {
2834 xmlSchemaErrorContext(ctxt, schema, node, child);
2835 if ((ctxt != NULL) && (ctxt->error != NULL))
2836 ctxt->error(ctxt->userData,
2837 "SimpleContent %s has unexpected content\n",
2844 * xmlSchemaParseComplexContent:
2845 * @ctxt: a schema validation context
2846 * @schema: the schema being built
2847 * @node: a subtree containing XML Schema informations
2849 * parse a XML schema ComplexContent definition
2850 * *WARNING* this interface is highly subject to change
2852 * Returns the type definition or NULL in case of error
2854 static xmlSchemaTypePtr
2855 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2858 xmlSchemaTypePtr type, subtype;
2859 xmlNodePtr child = NULL;
2862 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2866 snprintf((char *)name, 30, "complexContent %d", ctxt->counter++ + 1);
2867 type = xmlSchemaAddType(ctxt, schema, name);
2871 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
2872 type->id = xmlGetProp(node, BAD_CAST "id");
2874 child = node->children;
2875 if (IS_SCHEMA(child, "annotation")) {
2876 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2877 child = child->next;
2880 if (IS_SCHEMA(child, "restriction")) {
2881 subtype = (xmlSchemaTypePtr)
2882 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2883 child = child->next;
2884 } else if (IS_SCHEMA(child, "extension")) {
2885 subtype = (xmlSchemaTypePtr)
2886 xmlSchemaParseExtension(ctxt, schema, child);
2887 child = child->next;
2889 type->subtypes = subtype;
2890 if (child != NULL) {
2892 xmlSchemaErrorContext(ctxt, schema, node, child);
2893 if ((ctxt != NULL) && (ctxt->error != NULL))
2894 ctxt->error(ctxt->userData,
2895 "ComplexContent %s has unexpected content\n",
2902 * xmlSchemaParseComplexType:
2903 * @ctxt: a schema validation context
2904 * @schema: the schema being built
2905 * @node: a subtree containing XML Schema informations
2907 * parse a XML schema Complex Type definition
2908 * *WARNING* this interface is highly subject to change
2910 * Returns the type definition or NULL in case of error
2912 static xmlSchemaTypePtr
2913 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2916 xmlSchemaTypePtr type, subtype;
2917 xmlNodePtr child = NULL;
2919 xmlChar *oldcontainer;
2921 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2924 oldcontainer = ctxt->container;
2925 name = xmlGetProp(node, (const xmlChar *) "name");
2929 snprintf(buf, 99, "anontype%d", ctxt->counter++ + 1);
2930 name = xmlStrdup((xmlChar *) buf);
2934 xmlSchemaErrorContext(ctxt, schema, node, child);
2935 if ((ctxt != NULL) && (ctxt->error != NULL))
2936 ctxt->error(ctxt->userData, "complexType has no name\n");
2939 type = xmlSchemaAddType(ctxt, schema, name);
2945 type->type = XML_SCHEMA_TYPE_COMPLEX;
2946 type->id = xmlGetProp(node, BAD_CAST "id");
2947 ctxt->container = name;
2949 child = node->children;
2950 if (IS_SCHEMA(child, "annotation")) {
2951 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2952 child = child->next;
2954 if (IS_SCHEMA(child, "simpleContent")) {
2955 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
2956 child = child->next;
2957 } else if (IS_SCHEMA(child, "complexContent")) {
2958 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
2959 child = child->next;
2963 if (IS_SCHEMA(child, "all")) {
2964 subtype = xmlSchemaParseAll(ctxt, schema, child);
2965 child = child->next;
2966 } else if (IS_SCHEMA(child, "choice")) {
2967 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2968 child = child->next;
2969 } else if (IS_SCHEMA(child, "sequence")) {
2970 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2971 child = child->next;
2972 } else if (IS_SCHEMA(child, "group")) {
2973 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2974 child = child->next;
2976 if (subtype != NULL)
2977 type->subtypes = subtype;
2978 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2980 if (child != NULL) {
2982 xmlSchemaErrorContext(ctxt, schema, node, child);
2983 if ((ctxt != NULL) && (ctxt->error != NULL))
2984 ctxt->error(ctxt->userData,
2985 "ComplexType %s has unexpected content\n",
2988 ctxt->container = oldcontainer;
2995 * xmlSchemaParseSchema:
2996 * @ctxt: a schema validation context
2997 * @node: a subtree containing XML Schema informations
2999 * parse a XML schema definition from a node set
3000 * *WARNING* this interface is highly subject to change
3002 * Returns the internal XML Schema structure built from the resource or
3003 * NULL in case of error
3006 xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3008 xmlSchemaPtr schema = NULL;
3009 xmlSchemaAnnotPtr annot;
3010 xmlNodePtr child = NULL;
3014 if ((ctxt == NULL) || (node == NULL))
3017 nberrors = ctxt->nberrors;
3019 if (IS_SCHEMA(node, "schema")) {
3020 schema = xmlSchemaNewSchema(ctxt);
3023 schema->targetNamespace = xmlGetProp(node, BAD_CAST "targetNamespace");
3024 schema->id = xmlGetProp(node, BAD_CAST "id");
3025 schema->version = xmlGetProp(node, BAD_CAST "version");
3026 val = xmlGetProp(node, BAD_CAST "elementFormDefault");
3028 if (xmlStrEqual(val, BAD_CAST "qualified"))
3029 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3030 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3032 xmlSchemaErrorContext(ctxt, schema, node, child);
3033 if ((ctxt != NULL) && (ctxt->error != NULL)) {
3034 ctxt->error(ctxt->userData,
3035 "Invalid value %s for elementFormDefault\n",
3041 val = xmlGetProp(node, BAD_CAST "attributeFormDefault");
3043 if (xmlStrEqual(val, BAD_CAST "qualified"))
3044 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3045 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3047 xmlSchemaErrorContext(ctxt, schema, node, child);
3048 if ((ctxt != NULL) && (ctxt->error != NULL)) {
3049 ctxt->error(ctxt->userData,
3050 "Invalid value %s for elementFormDefault\n",
3057 child = node->children;
3058 while ((IS_SCHEMA(child, "include")) ||
3059 (IS_SCHEMA(child, "import")) ||
3060 (IS_SCHEMA(child, "redefine")) ||
3061 (IS_SCHEMA(child, "annotation"))) {
3062 if (IS_SCHEMA(child, "annotation")) {
3063 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3064 if (schema->annot == NULL)
3065 schema->annot = annot;
3067 xmlSchemaFreeAnnot(annot);
3068 } else if (IS_SCHEMA(child, "include")) {
3070 } else if (IS_SCHEMA(child, "import")) {
3071 xmlSchemaParseImport(ctxt, schema, child);
3072 } else if (IS_SCHEMA(child, "redefine")) {
3075 child = child->next;
3077 while (child != NULL) {
3078 if (IS_SCHEMA(child, "complexType")) {
3079 xmlSchemaParseComplexType(ctxt, schema, child);
3080 child = child->next;
3081 } else if (IS_SCHEMA(child, "simpleType")) {
3082 xmlSchemaParseSimpleType(ctxt, schema, child);
3083 child = child->next;
3084 } else if (IS_SCHEMA(child, "element")) {
3085 xmlSchemaParseElement(ctxt, schema, child, 1);
3086 child = child->next;
3087 } else if (IS_SCHEMA(child, "attribute")) {
3088 xmlSchemaParseAttribute(ctxt, schema, child);
3089 child = child->next;
3090 } else if (IS_SCHEMA(child, "attributeGroup")) {
3091 xmlSchemaParseAttributeGroup(ctxt, schema, child);
3092 child = child->next;
3093 } else if (IS_SCHEMA(child, "group")) {
3094 xmlSchemaParseGroup(ctxt, schema, child);
3095 child = child->next;
3096 } else if (IS_SCHEMA(child, "notation")) {
3097 xmlSchemaParseNotation(ctxt, schema, child);
3098 child = child->next;
3101 xmlSchemaErrorContext(ctxt, schema, node, child);
3102 if ((ctxt != NULL) && (ctxt->error != NULL))
3103 ctxt->error(ctxt->userData,
3104 "Schemas: unexpected element %s here \n",
3106 child = child->next;
3108 while (IS_SCHEMA(child, "annotation")) {
3109 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3110 if (schema->annot == NULL)
3111 schema->annot = annot;
3113 xmlSchemaFreeAnnot(annot);
3114 child = child->next;
3118 if (ctxt->nberrors != 0) {
3119 if (schema != NULL) {
3120 xmlSchemaFree(schema);
3124 ctxt->nberrors = nberrors;
3127 xmlGenericError(xmlGenericErrorContext,
3128 "xmlSchemaParse() failed\n");
3134 /************************************************************************
3136 * Validating using Schemas *
3138 ************************************************************************/
3140 /************************************************************************
3142 * Reading/Writing Schemas *
3144 ************************************************************************/
3147 * xmlSchemaNewParserCtxt:
3148 * @URL: the location of the schema
3150 * Create an XML Schemas parse context for that file/resource expected
3151 * to contain an XML Schemas file.
3153 * Returns the parser context or NULL in case of error
3155 xmlSchemaParserCtxtPtr
3156 xmlSchemaNewParserCtxt(const char *URL) {
3157 xmlSchemaParserCtxtPtr ret;
3162 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3164 xmlGenericError(xmlGenericErrorContext,
3165 "Failed to allocate new schama parser context for %s\n", URL);
3168 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3169 ret->URL = xmlStrdup((const xmlChar *)URL);
3174 * xmlSchemaNewMemParserCtxt:
3175 * @buffer: a pointer to a char array containing the schemas
3176 * @size: the size of the array
3178 * Create an XML Schemas parse context for that memory buffer expected
3179 * to contain an XML Schemas file.
3181 * Returns the parser context or NULL in case of error
3183 xmlSchemaParserCtxtPtr
3184 xmlSchemaNewMemParserCtxt(const char *buffer, int size) {
3185 xmlSchemaParserCtxtPtr ret;
3187 if ((buffer == NULL) || (size <= 0))
3190 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3192 xmlGenericError(xmlGenericErrorContext,
3193 "Failed to allocate new schama parser context\n");
3196 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3197 ret->buffer = buffer;
3203 * xmlSchemaFreeParserCtxt:
3204 * @ctxt: the schema parser context
3206 * Free the resources associated to the schema parser context
3209 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) {
3212 if (ctxt->URL != NULL)
3214 if (ctxt->doc != NULL)
3215 xmlFreeDoc(ctxt->doc);
3219 /************************************************************************
3221 * Building the content models *
3223 ************************************************************************/
3225 * xmlSchemaBuildAContentModel:
3226 * @type: the schema type definition
3227 * @ctxt: the schema parser context
3228 * @name: the element name whose content is being built
3230 * Generate the automata sequence needed for that type
3233 xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
3234 xmlSchemaParserCtxtPtr ctxt,
3235 const xmlChar *name) {
3237 xmlGenericError(xmlGenericErrorContext,
3238 "Found unexpected type = NULL in %s content model\n",
3242 switch (type->type) {
3243 case XML_SCHEMA_TYPE_ANY:
3244 /* TODO : handle the namespace too */
3245 /* TODO : make that a specific transition type */
3247 ctxt->state = xmlAutomataNewTransition(ctxt->am, ctxt->state,
3248 NULL, BAD_CAST "*", NULL);
3250 case XML_SCHEMA_TYPE_ELEMENT: {
3251 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3252 /* TODO : handle the namespace too */
3253 xmlAutomataStatePtr oldstate = ctxt->state;
3254 if (elem->maxOccurs >= UNBOUNDED) {
3255 if (elem->minOccurs > 1) {
3256 xmlAutomataStatePtr tmp;
3259 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3261 oldstate = ctxt->state;
3263 counter = xmlAutomataNewCounter(ctxt->am,
3264 elem->minOccurs - 1, UNBOUNDED);
3266 if (elem->refDecl != NULL) {
3267 xmlSchemaBuildAContentModel(
3268 (xmlSchemaTypePtr) elem->refDecl,
3269 ctxt, elem->refDecl->name);
3271 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3272 ctxt->state, NULL, elem->name, type);
3275 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3277 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3281 if (elem->refDecl != NULL) {
3282 xmlSchemaBuildAContentModel(
3283 (xmlSchemaTypePtr) elem->refDecl,
3284 ctxt, elem->refDecl->name);
3286 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3287 ctxt->state, NULL, elem->name, type);
3289 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
3290 if (elem->minOccurs == 0) {
3291 /* basically an elem* */
3292 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3295 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3296 xmlAutomataStatePtr tmp;
3299 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3301 oldstate = ctxt->state;
3303 counter = xmlAutomataNewCounter(ctxt->am,
3304 elem->minOccurs - 1, elem->maxOccurs - 1);
3306 if (elem->refDecl != NULL) {
3307 xmlSchemaBuildAContentModel(
3308 (xmlSchemaTypePtr) elem->refDecl,
3309 ctxt, elem->refDecl->name);
3311 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3312 ctxt->state, NULL, elem->name, type);
3315 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3317 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3319 if (elem->minOccurs == 0) {
3320 /* basically an elem? */
3321 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3325 if (elem->refDecl != NULL) {
3326 xmlSchemaBuildAContentModel(
3327 (xmlSchemaTypePtr) elem->refDecl,
3328 ctxt, elem->refDecl->name);
3330 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3331 ctxt->state, NULL, elem->name, type);
3333 if (elem->minOccurs == 0) {
3334 /* basically an elem? */
3335 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3340 case XML_SCHEMA_TYPE_SEQUENCE: {
3341 xmlSchemaTypePtr subtypes;
3344 * If max and min occurances are default (1) then
3345 * simply iterate over the subtypes
3347 if ((type->minOccurs == 1 ) && (type->maxOccurs == 1)) {
3348 subtypes = type->subtypes;
3349 while (subtypes != NULL) {
3350 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3351 subtypes = subtypes->next;
3354 xmlAutomataStatePtr oldstate = ctxt->state;
3355 if (type->maxOccurs >= UNBOUNDED) {
3356 if (type->minOccurs > 1) {
3357 xmlAutomataStatePtr tmp;
3360 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3362 oldstate = ctxt->state;
3364 counter = xmlAutomataNewCounter(ctxt->am,
3365 type->minOccurs - 1, UNBOUNDED);
3367 subtypes = type->subtypes;
3368 while (subtypes != NULL) {
3369 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3370 subtypes = subtypes->next;
3373 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3375 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3379 subtypes = type->subtypes;
3380 while (subtypes != NULL) {
3381 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3382 subtypes = subtypes->next;
3384 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
3385 if (type->minOccurs == 0) {
3386 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3390 } else if ((type->maxOccurs > 1) || (type->minOccurs > 1)) {
3391 xmlAutomataStatePtr tmp;
3394 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3396 oldstate = ctxt->state;
3398 counter = xmlAutomataNewCounter(ctxt->am,
3399 type->minOccurs - 1, type->maxOccurs - 1);
3401 subtypes = type->subtypes;
3402 while (subtypes != NULL) {
3403 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3404 subtypes = subtypes->next;
3407 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3409 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3411 if (type->minOccurs == 0) {
3412 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3416 subtypes = type->subtypes;
3417 while (subtypes != NULL) {
3418 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3419 subtypes = subtypes->next;
3421 if (type->minOccurs == 0) {
3422 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3428 case XML_SCHEMA_TYPE_CHOICE: {
3429 xmlSchemaTypePtr subtypes;
3430 xmlAutomataStatePtr start, end;
3432 start = ctxt->state;
3433 end = xmlAutomataNewState(ctxt->am);
3436 * iterate over the subtypes and remerge the end with an
3437 * epsilon transition
3439 if (type->maxOccurs == 1) {
3440 subtypes = type->subtypes;
3441 while (subtypes != NULL) {
3442 ctxt->state = start;
3443 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3444 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
3445 subtypes = subtypes->next;
3449 xmlAutomataStatePtr hop;
3450 int maxOccurs = type->maxOccurs == UNBOUNDED ?
3451 UNBOUNDED : type->maxOccurs - 1;
3452 int minOccurs = type->minOccurs < 1 ? 0 : type->minOccurs - 1;
3455 * use a counter to keep track of the number of transtions
3456 * which went through the choice.
3458 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
3459 hop = xmlAutomataNewState(ctxt->am);
3461 subtypes = type->subtypes;
3462 while (subtypes != NULL) {
3463 ctxt->state = start;
3464 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3465 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
3466 subtypes = subtypes->next;
3468 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
3469 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
3471 if (type->minOccurs == 0) {
3472 xmlAutomataNewEpsilon(ctxt->am, start, end);
3477 case XML_SCHEMA_TYPE_ALL: {
3478 xmlAutomataStatePtr start;
3479 xmlSchemaTypePtr subtypes;
3480 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3483 subtypes = type->subtypes;
3484 if (subtypes == NULL)
3486 start = ctxt->state;
3487 while (subtypes != NULL) {
3488 ctxt->state = start;
3489 elem = (xmlSchemaElementPtr) subtypes;
3491 /* TODO : handle the namespace too */
3492 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
3493 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state, ctxt->state,
3494 elem->name, 1, 1, subtypes);
3496 xmlAutomataNewCountTrans(ctxt->am, ctxt->state, ctxt->state,
3497 elem->name, elem->minOccurs,
3498 elem->maxOccurs, subtypes);
3500 subtypes = subtypes->next;
3502 lax = type->minOccurs == 0;
3503 ctxt->state = xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
3507 case XML_SCHEMA_TYPE_RESTRICTION:
3508 if (type->subtypes != NULL)
3509 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3511 case XML_SCHEMA_TYPE_EXTENSION:
3512 if (type->baseType != NULL) {
3513 xmlSchemaTypePtr subtypes;
3515 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
3516 subtypes = type->subtypes;
3517 while (subtypes != NULL) {
3518 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3519 subtypes = subtypes->next;
3521 } else if (type->subtypes != NULL)
3522 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3524 case XML_SCHEMA_TYPE_GROUP:
3525 if (type->subtypes == NULL) {
3527 case XML_SCHEMA_TYPE_COMPLEX:
3528 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
3529 if (type->subtypes != NULL)
3530 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3533 xmlGenericError(xmlGenericErrorContext,
3534 "Found unexpected type %d in %s content model\n",
3540 * xmlSchemaBuildContentModel:
3541 * @elem: the element
3542 * @ctxt: the schema parser context
3543 * @name: the element name
3545 * Builds the content model of the element.
3548 xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
3549 xmlSchemaParserCtxtPtr ctxt,
3550 const xmlChar *name) {
3551 xmlAutomataStatePtr start;
3553 if (elem->contModel != NULL)
3555 if (elem->subtypes == NULL) {
3556 elem->contentType = XML_SCHEMA_CONTENT_ANY;
3559 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
3561 if (elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC)
3564 #ifdef DEBUG_CONTENT
3565 xmlGenericError(xmlGenericErrorContext,
3566 "Building content model for %s\n", name);
3569 ctxt->am = xmlNewAutomata();
3570 if (ctxt->am == NULL) {
3571 xmlGenericError(xmlGenericErrorContext,
3572 "Cannot create automata for elem %s\n", name);
3575 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3576 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3577 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
3578 elem->contModel = xmlAutomataCompile(ctxt->am);
3579 if (elem->contModel == NULL) {
3580 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3581 if ((ctxt != NULL) && (ctxt->error != NULL))
3582 ctxt->error(ctxt->userData,
3583 "failed to compile %s content model\n",
3585 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
3587 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
3588 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3589 if ((ctxt != NULL) && (ctxt->error != NULL))
3590 ctxt->error(ctxt->userData,
3591 "Content model of %s is not determinist:\n", name);
3592 ctxt->err = XML_SCHEMAS_ERR_NOTDETERMINIST;
3595 #ifdef DEBUG_CONTENT_REGEXP
3596 xmlGenericError(xmlGenericErrorContext,
3597 "Content model of %s:\n", name);
3598 xmlRegexpPrint(stderr, elem->contModel);
3602 xmlFreeAutomata(ctxt->am);
3607 * xmlSchemaRefFixupCallback:
3608 * @elem: the schema element context
3609 * @ctxt: the schema parser context
3611 * Free the resources associated to the schema parser context
3614 xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
3615 xmlSchemaParserCtxtPtr ctxt,
3616 const xmlChar *name,
3617 const xmlChar *context ATTRIBUTE_UNUSED,
3618 const xmlChar *namespace ATTRIBUTE_UNUSED)
3620 if ((ctxt == NULL) || (elem == NULL))
3622 if (elem->ref != NULL) {
3623 xmlSchemaElementPtr elemDecl;
3625 if (elem->subtypes != NULL) {
3627 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3628 if ((ctxt != NULL) && (ctxt->error != NULL))
3629 ctxt->error(ctxt->userData,
3630 "Schemas: element %s have both ref and subtype\n",
3634 elemDecl = xmlHashLookup2(ctxt->schema->elemDecl,
3635 elem->ref, elem->refNs);
3637 if (elemDecl == NULL) {
3639 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3640 if ((ctxt != NULL) && (ctxt->error != NULL))
3641 ctxt->error(ctxt->userData,
3642 "Schemas: element %s ref to %s not found\n",
3646 elem->refDecl = elemDecl;
3647 } else if (elem->namedType != NULL) {
3648 xmlSchemaTypePtr typeDecl;
3650 if (elem->subtypes != NULL) {
3652 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3653 if ((ctxt != NULL) && (ctxt->error != NULL))
3654 ctxt->error(ctxt->userData,
3655 "Schemas: element %s have both type and subtype\n",
3659 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3662 if (typeDecl == NULL) {
3664 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3665 if ((ctxt != NULL) && (ctxt->error != NULL))
3666 ctxt->error(ctxt->userData,
3667 "Schemas: element %s type %s not found\n",
3668 name, elem->namedType);
3671 elem->subtypes = typeDecl;
3676 * xmlSchemaTypeFixup:
3677 * @typeDecl: the schema type definition
3678 * @ctxt: the schema parser context
3680 * Fixes the content model of the type.
3683 xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
3684 xmlSchemaParserCtxtPtr ctxt,
3685 const xmlChar *name)
3687 if (typeDecl == NULL)
3690 name = typeDecl->name;
3691 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
3692 switch (typeDecl->type) {
3693 case XML_SCHEMA_TYPE_SIMPLE_CONTENT: {
3694 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3695 if (typeDecl->subtypes != NULL)
3696 typeDecl->contentType = typeDecl->subtypes->contentType;
3699 case XML_SCHEMA_TYPE_RESTRICTION: {
3700 if (typeDecl->subtypes != NULL)
3701 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3703 if (typeDecl->base != NULL) {
3704 xmlSchemaTypePtr baseType;
3706 baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3708 if (baseType == NULL) {
3710 if ((ctxt != NULL) && (ctxt->error != NULL))
3711 ctxt->error(ctxt->userData,
3712 "Schemas: type %s base type %s not found\n",
3713 name, typeDecl->base);
3715 typeDecl->baseType = baseType;
3717 if (typeDecl->subtypes == NULL)
3719 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3720 else if ((typeDecl->subtypes->subtypes == NULL) &&
3721 ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3722 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3724 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3725 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3726 (typeDecl->subtypes->subtypes == NULL))
3728 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3730 /* 1.2 and 2.X are applied at the other layer */
3731 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3735 case XML_SCHEMA_TYPE_EXTENSION: {
3736 xmlSchemaContentType explicitContentType;
3737 xmlSchemaTypePtr base;
3739 if (typeDecl->base != NULL) {
3740 xmlSchemaTypePtr baseType;
3742 baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3744 if (baseType == NULL) {
3746 if ((ctxt != NULL) && (ctxt->error != NULL))
3747 ctxt->error(ctxt->userData,
3748 "Schemas: type %s base type %s not found\n",
3749 name, typeDecl->base);
3751 typeDecl->baseType = baseType;
3753 if (typeDecl->subtypes != NULL)
3754 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3756 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
3757 if (typeDecl->subtypes == NULL)
3759 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3760 else if ((typeDecl->subtypes->subtypes == NULL) &&
3761 ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3762 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3764 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3765 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3766 (typeDecl->subtypes->subtypes == NULL))
3768 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3770 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3774 xmlSchemaErrorContext(ctxt, NULL, typeDecl->node, NULL);
3775 if ((ctxt != NULL) && (ctxt->error != NULL))
3776 ctxt->error(ctxt->userData,
3777 "Schemas: base type %s of type %s not found\n",
3778 typeDecl->base, name);
3781 xmlSchemaTypeFixup(base, ctxt, NULL);
3782 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
3784 typeDecl->contentType = base->contentType;
3785 } else if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
3786 /* 2.2 imbitable ! */
3787 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3789 /* 2.3 imbitable pareil ! */
3790 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3794 case XML_SCHEMA_TYPE_COMPLEX: {
3795 if (typeDecl->subtypes == NULL) {
3796 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3798 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3799 typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3801 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3802 if (typeDecl->subtypes != NULL)
3803 typeDecl->contentType =
3804 typeDecl->subtypes->contentType;
3809 case XML_SCHEMA_TYPE_COMPLEX_CONTENT: {
3810 if (typeDecl->subtypes == NULL) {
3811 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3813 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3814 typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3816 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3817 if (typeDecl->subtypes != NULL)
3818 typeDecl->contentType =
3819 typeDecl->subtypes->contentType;
3824 case XML_SCHEMA_TYPE_SEQUENCE:
3825 case XML_SCHEMA_TYPE_GROUP:
3826 case XML_SCHEMA_TYPE_ALL:
3827 case XML_SCHEMA_TYPE_CHOICE:
3828 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3830 case XML_SCHEMA_TYPE_BASIC:
3831 case XML_SCHEMA_TYPE_ANY:
3832 case XML_SCHEMA_TYPE_FACET:
3833 case XML_SCHEMA_TYPE_SIMPLE:
3834 case XML_SCHEMA_TYPE_UR:
3835 case XML_SCHEMA_TYPE_ELEMENT:
3836 case XML_SCHEMA_TYPE_ATTRIBUTE:
3837 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
3838 case XML_SCHEMA_TYPE_NOTATION:
3839 case XML_SCHEMA_TYPE_LIST:
3840 case XML_SCHEMA_TYPE_UNION:
3841 case XML_SCHEMA_FACET_MININCLUSIVE:
3842 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3843 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3844 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
3845 case XML_SCHEMA_FACET_TOTALDIGITS:
3846 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3847 case XML_SCHEMA_FACET_PATTERN:
3848 case XML_SCHEMA_FACET_ENUMERATION:
3849 case XML_SCHEMA_FACET_WHITESPACE:
3850 case XML_SCHEMA_FACET_LENGTH:
3851 case XML_SCHEMA_FACET_MAXLENGTH:
3852 case XML_SCHEMA_FACET_MINLENGTH:
3853 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
3858 if (typeDecl->node != NULL) {
3859 xmlGenericError(xmlGenericErrorContext,
3860 "Type of %s : %s:%d :", name, typeDecl->node->doc->URL,
3861 xmlGetLineNo(typeDecl->node));
3863 xmlGenericError(xmlGenericErrorContext,
3864 "Type of %s :", name);
3866 switch (typeDecl->contentType) {
3867 case XML_SCHEMA_CONTENT_SIMPLE:
3868 xmlGenericError(xmlGenericErrorContext,
3870 case XML_SCHEMA_CONTENT_ELEMENTS:
3871 xmlGenericError(xmlGenericErrorContext,
3872 "elements\n"); break;
3873 case XML_SCHEMA_CONTENT_UNKNOWN:
3874 xmlGenericError(xmlGenericErrorContext,
3875 "unknown !!!\n"); break;
3876 case XML_SCHEMA_CONTENT_EMPTY:
3877 xmlGenericError(xmlGenericErrorContext,
3879 case XML_SCHEMA_CONTENT_MIXED:
3880 xmlGenericError(xmlGenericErrorContext,
3882 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
3883 xmlGenericError(xmlGenericErrorContext,
3884 "mixed or elems\n"); break;
3885 case XML_SCHEMA_CONTENT_BASIC:
3886 xmlGenericError(xmlGenericErrorContext,
3889 xmlGenericError(xmlGenericErrorContext,
3890 "not registered !!!\n"); break;
3896 * xmlSchemaCheckFacet:
3898 * @typeDecl: the schema type definition
3899 * @ctxt: the schema parser context or NULL
3900 * @name: name of the type
3902 * Checks the default values types, especially for facets
3904 * Returns 0 if okay or -1 in cae of error
3907 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
3908 xmlSchemaTypePtr typeDecl,
3909 xmlSchemaParserCtxtPtr ctxt,
3910 const xmlChar *name)
3912 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
3915 if (nonNegativeIntegerType == NULL) {
3916 nonNegativeIntegerType = xmlSchemaGetPredefinedType(
3917 BAD_CAST "nonNegativeInteger", xmlSchemaNs);
3919 switch (facet->type) {
3920 case XML_SCHEMA_FACET_MININCLUSIVE:
3921 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3922 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3923 case XML_SCHEMA_FACET_MAXEXCLUSIVE: {
3925 * Okay we need to validate the value
3928 xmlSchemaValidCtxtPtr vctxt;
3930 vctxt = xmlSchemaNewValidCtxt(NULL);
3933 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3935 facet->val = vctxt->value;
3936 vctxt->value = NULL;
3937 if (facet->val == NULL) {
3941 xmlSchemaErrorContext(ctxt, NULL,
3943 ctxt->error(ctxt->userData,
3944 "Schemas: type %s facet value %s invalid\n",
3945 name, facet->value);
3949 xmlSchemaFreeValidCtxt(vctxt);
3952 case XML_SCHEMA_FACET_ENUMERATION: {
3954 * Okay we need to validate the value
3957 xmlSchemaValidCtxtPtr vctxt;
3960 vctxt = xmlSchemaNewValidCtxt(NULL);
3963 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3968 xmlSchemaErrorContext(ctxt, NULL,
3970 ctxt->error(ctxt->userData,
3971 "Schemas: type %s enumeration value %s invalid\n",
3972 name, facet->value);
3976 xmlSchemaFreeValidCtxt(vctxt);
3979 case XML_SCHEMA_FACET_PATTERN:
3980 facet->regexp = xmlRegexpCompile(facet->value);
3981 if (facet->regexp == NULL) {
3985 ctxt->error(ctxt->userData,
3986 "Schemas: type %s facet regexp %s invalid\n",
3987 name, facet->value);
3992 case XML_SCHEMA_FACET_TOTALDIGITS:
3993 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3994 case XML_SCHEMA_FACET_LENGTH:
3995 case XML_SCHEMA_FACET_MAXLENGTH:
3996 case XML_SCHEMA_FACET_MINLENGTH: {
3999 tmp = xmlSchemaValidatePredefinedType(
4000 nonNegativeIntegerType, facet->value,
4006 xmlSchemaErrorContext(ctxt, NULL,
4008 ctxt->error(ctxt->userData,
4009 "Schemas: type %s facet value %s invalid\n",
4010 name, facet->value);
4016 case XML_SCHEMA_FACET_WHITESPACE: {
4017 if (xmlStrEqual(facet->value, BAD_CAST"preserve")) {
4018 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4019 } else if (xmlStrEqual(facet->value,
4020 BAD_CAST"replace")) {
4021 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4022 } else if (xmlStrEqual(facet->value,
4023 BAD_CAST"collapse")) {
4024 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4028 xmlSchemaErrorContext(ctxt, NULL,
4030 ctxt->error(ctxt->userData,
4031 "Schemas: type %s whiteSpace value %s invalid\n",
4032 name, facet->value);
4044 * xmlSchemaCheckDefaults:
4045 * @typeDecl: the schema type definition
4046 * @ctxt: the schema parser context
4048 * Checks the default values types, especially for facets
4051 xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
4052 xmlSchemaParserCtxtPtr ctxt,
4053 const xmlChar *name)
4056 name = typeDecl->name;
4057 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
4058 if (typeDecl->facets != NULL) {
4059 xmlSchemaFacetPtr facet = typeDecl->facets;
4060 while (facet != NULL) {
4061 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4062 facet = facet->next;
4069 * xmlSchemaAttrGrpFixup:
4070 * @attrgrpDecl: the schema attribute definition
4071 * @ctxt: the schema parser context
4072 * @name: the attribute name
4074 * Fixes finish doing the computations on the attributes definitions
4077 xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
4078 xmlSchemaParserCtxtPtr ctxt,
4079 const xmlChar *name)
4082 name = attrgrpDecl->name;
4083 if (attrgrpDecl->attributes != NULL)
4085 if (attrgrpDecl->ref != NULL) {
4086 xmlSchemaAttributeGroupPtr ref;
4088 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4089 attrgrpDecl->refNs);
4092 xmlSchemaErrorContext(ctxt, NULL, attrgrpDecl->node, NULL);
4093 if ((ctxt != NULL) && (ctxt->error != NULL))
4094 ctxt->error(ctxt->userData,
4095 "Schemas: attribute group %s reference %s not found\n",
4096 name, attrgrpDecl->ref);
4099 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4100 attrgrpDecl->attributes = ref->attributes;
4103 xmlSchemaErrorContext(ctxt, NULL, attrgrpDecl->node, NULL);
4104 if ((ctxt != NULL) && (ctxt->error != NULL))
4105 ctxt->error(ctxt->userData,
4106 "Schemas: attribute %s has no attributes nor reference\n",
4112 * xmlSchemaAttrFixup:
4113 * @attrDecl: the schema attribute definition
4114 * @ctxt: the schema parser context
4115 * @name: the attribute name
4117 * Fixes finish doing the computations on the attributes definitions
4120 xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
4121 xmlSchemaParserCtxtPtr ctxt,
4122 const xmlChar *name)
4125 name = attrDecl->name;
4126 if (attrDecl->subtypes != NULL)
4128 if (attrDecl->typeName != NULL) {
4129 xmlSchemaTypePtr type;
4131 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4135 xmlSchemaErrorContext(ctxt, NULL, attrDecl->node, NULL);
4136 if ((ctxt != NULL) && (ctxt->error != NULL))
4137 ctxt->error(ctxt->userData,
4138 "Schemas: attribute %s type %s not found\n",
4139 name, attrDecl->typeName);
4141 attrDecl->subtypes = type;
4142 } else if (attrDecl->ref != NULL) {
4143 xmlSchemaAttributePtr ref;
4145 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4149 xmlSchemaErrorContext(ctxt, NULL, attrDecl->node, NULL);
4150 if ((ctxt != NULL) && (ctxt->error != NULL))
4151 ctxt->error(ctxt->userData,
4152 "Schemas: attribute %s reference %s not found\n",
4153 name, attrDecl->ref);
4156 xmlSchemaAttrFixup(ref, ctxt, NULL);
4157 attrDecl->subtypes = ref->subtypes;
4160 xmlSchemaErrorContext(ctxt, NULL, attrDecl->node, NULL);
4161 if ((ctxt != NULL) && (ctxt->error != NULL))
4162 ctxt->error(ctxt->userData,
4163 "Schemas: attribute %s has no type nor reference\n",
4170 * @ctxt: a schema validation context
4172 * parse a schema definition resource and build an internal
4173 * XML Shema struture which can be used to validate instances.
4174 * *WARNING* this interface is highly subject to change
4176 * Returns the internal XML Schema structure built from the resource or
4177 * NULL in case of error
4180 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4182 xmlSchemaPtr ret = NULL;
4184 xmlNodePtr root, cur, delete;
4187 xmlSchemaInitTypes();
4192 nberrors = ctxt->nberrors;
4195 ctxt->container = NULL;
4198 * First step is to parse the input document into an DOM/Infoset
4200 if (ctxt->URL != NULL) {
4201 doc = xmlParseFile((const char *) ctxt->URL);
4204 if (ctxt->error != NULL)
4205 ctxt->error(ctxt->userData,
4206 "xmlSchemaParse: could not load %s\n", ctxt->URL);
4209 } else if (ctxt->buffer != NULL) {
4210 doc = xmlParseMemory(ctxt->buffer, ctxt->size);
4213 if (ctxt->error != NULL)
4214 ctxt->error(ctxt->userData,
4215 "xmlSchemaParse: could not parse schemas\n");
4218 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
4219 ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
4222 if (ctxt->error != NULL)
4223 ctxt->error(ctxt->userData,
4224 "xmlSchemaParse: nothing to parse\n");
4229 * Then extract the root and Schema parse it
4231 root = xmlDocGetRootElement(doc);
4234 if (ctxt->error != NULL)
4235 ctxt->error(ctxt->userData, "xmlSchemaParse: %s is empty\n",
4241 * Remove all the blank text nodes
4245 while (cur != NULL) {
4246 if (delete != NULL) {
4247 xmlUnlinkNode(delete);
4248 xmlFreeNode(delete);
4251 if (cur->type == XML_TEXT_NODE) {
4252 if (IS_BLANK_NODE(cur)) {
4253 if (xmlNodeGetSpacePreserve(cur) != 1) {
4257 } else if ((cur->type != XML_ELEMENT_NODE) &&
4258 (cur->type != XML_CDATA_SECTION_NODE)) {
4266 if (cur->children != NULL) {
4267 if ((cur->children->type != XML_ENTITY_DECL) &&
4268 (cur->children->type != XML_ENTITY_REF_NODE) &&
4269 (cur->children->type != XML_ENTITY_NODE)) {
4270 cur = cur->children;
4275 if (cur->next != NULL) {
4288 if (cur->next != NULL) {
4292 } while (cur != NULL);
4294 if (delete != NULL) {
4295 xmlUnlinkNode(delete);
4296 xmlFreeNode(delete);
4301 * Then do the parsing for good
4303 ret = xmlSchemaParseSchema(ctxt, root);
4309 * Then fix all the references.
4312 xmlHashScanFull(ret->elemDecl,
4313 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
4316 * Then fixup all types properties
4318 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4321 * Then build the content model for all elements
4323 xmlHashScan(ret->elemDecl,
4324 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
4327 * Then check the defaults part of the type like facets values
4329 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt);
4332 * Then fixup all attributes declarations
4334 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4337 * Then fixup all attributes group declarations
4339 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup, ctxt);
4341 if (ctxt->nberrors != 0) {
4349 * xmlSchemaSetParserErrors:
4350 * @ctxt: a schema validation context
4351 * @err: the error callback
4352 * @warn: the warning callback
4353 * @ctx: contextual data for the callbacks
4355 * Set the callback functions used to handle errors for a validation context
4358 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
4359 xmlSchemaValidityErrorFunc err,
4360 xmlSchemaValidityWarningFunc warn, void *ctx) {
4364 ctxt->warning = warn;
4365 ctxt->userData = ctx;
4369 * xmlSchemaFacetTypeToString:
4370 * @type: the facet type
4372 * Convert the xmlSchemaTypeType to a char string.
4374 * Returns the char string representation of the facet type if the
4375 * type is a facet and an "Internal Error" string otherwise.
4378 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
4381 case XML_SCHEMA_FACET_PATTERN:
4383 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4384 return ("maxExclusive");
4385 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4386 return ("maxInclusive");
4387 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4388 return ("minExclusive");
4389 case XML_SCHEMA_FACET_MININCLUSIVE:
4390 return ("minInclusive");
4391 case XML_SCHEMA_FACET_WHITESPACE:
4392 return ("whiteSpace");
4393 case XML_SCHEMA_FACET_ENUMERATION:
4394 return ("enumeration");
4395 case XML_SCHEMA_FACET_LENGTH:
4397 case XML_SCHEMA_FACET_MAXLENGTH:
4398 return ("maxLength");
4399 case XML_SCHEMA_FACET_MINLENGTH:
4400 return ("minLength");
4401 case XML_SCHEMA_FACET_TOTALDIGITS:
4402 return ("totalDigits");
4403 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4404 return ("fractionDigits");
4408 return ("Internal Error");
4412 * xmlSchemaValidateFacets:
4413 * @ctxt: a schema validation context
4414 * @base: the base type
4415 * @facets: the list of facets to check
4416 * @value: the lexical repr of the value to validate
4417 * @val: the precomputed value
4419 * Check a value against all facet conditions
4421 * Returns 0 if the element is schemas valid, a positive error code
4422 * number otherwise and -1 in case of internal or API error.
4425 xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
4426 xmlSchemaTypePtr base,
4427 xmlSchemaFacetPtr facets,
4431 xmlSchemaTypeType type;
4432 xmlSchemaFacetPtr facet = facets;
4434 while (facet != NULL) {
4436 if (type == XML_SCHEMA_FACET_ENUMERATION) {
4439 while (facet != NULL) {
4440 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
4444 facet = facet->next;
4447 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
4452 if (ctxt->error != NULL)
4453 ctxt->error(ctxt->userData,
4454 "Failed to validate type with facet %s\n",
4455 xmlSchemaFacetTypeToString(type));
4456 ctxt->err = XML_SCHEMAS_ERR_FACET;
4459 facet = facet->next;
4464 /************************************************************************
4466 * Simple type validation *
4468 ************************************************************************/
4471 * xmlSchemaValidateSimpleValue:
4472 * @ctxt: a schema validation context
4473 * @type: the type declaration
4474 * @value: the value to validate
4476 * Validate a value against a simple type
4478 * Returns 0 if the value is valid, a positive error code
4479 * number otherwise and -1 in case of internal or API error.
4482 xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
4483 xmlSchemaTypePtr type,
4487 * First normalize the value accordingly to Schema Datatype
4488 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
4491 * Then check the normalized value against the lexical space of the
4494 if (type->type == XML_SCHEMA_TYPE_BASIC) {
4495 if (ctxt->value != NULL) {
4496 xmlSchemaFreeValue(ctxt->value);
4499 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
4503 if (ctxt->error != NULL)
4504 ctxt->error(ctxt->userData,
4505 "Failed to validate basic type %s\n", type->name);
4506 ctxt->err = XML_SCHEMAS_ERR_VALUE;
4508 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
4509 xmlSchemaTypePtr base;
4510 xmlSchemaFacetPtr facet;
4512 base = type->baseType;
4514 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4515 } else if (type->subtypes != NULL) {
4519 * Do not validate facets when working on building the Schemas
4521 if (ctxt->schema != NULL) {
4523 facet = type->facets;
4524 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
4527 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
4528 xmlSchemaTypePtr base;
4530 base = type->subtypes;
4532 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4536 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
4537 xmlSchemaTypePtr base;
4538 xmlChar *cur, *end, tmp;
4541 base = type->subtypes;
4543 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4545 if (ctxt->error != NULL) {
4546 xmlSchemaErrorContext(NULL, ctxt->schema, type->node, NULL);
4547 ctxt->error(ctxt->userData,
4548 "Internal: List type %s has no base type\n",
4555 while (IS_BLANK(*cur)) cur++;
4557 while ((*end != 0) && (!(IS_BLANK(*end)))) end++;
4562 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, cur);
4567 } while (*cur != 0);
4574 /************************************************************************
4576 * DOM Validation code *
4578 ************************************************************************/
4580 static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
4582 static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
4583 xmlNodePtr elem, xmlSchemaAttributePtr attributes);
4584 static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
4585 xmlNodePtr elem, xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type);
4588 * xmlSchemaRegisterAttributes:
4589 * @ctxt: a schema validation context
4590 * @attrs: a list of attributes
4592 * Register the list of attributes as the set to be validated on that element
4594 * Returns -1 in case of error, 0 otherwise
4597 xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt,
4599 while (attrs != NULL) {
4600 if ((attrs->ns != NULL) &&
4601 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
4602 attrs = attrs->next;
4605 if (ctxt->attrNr >= ctxt->attrMax) {
4606 xmlSchemaAttrStatePtr tmp;
4609 tmp = (xmlSchemaAttrStatePtr)
4610 xmlRealloc(ctxt->attr, ctxt->attrMax *
4611 sizeof(xmlSchemaAttrState));
4618 ctxt->attr[ctxt->attrNr].attr = attrs;
4619 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
4621 attrs = attrs->next;
4627 * xmlSchemaCheckAttributes:
4628 * @ctxt: a schema validation context
4629 * @node: the node carrying it.
4631 * Check that the registered set of attributes on the current node
4632 * has been properly validated.
4634 * Returns 0 if validity constraints are met, 1 otherwise.
4637 xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4641 for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
4642 if (ctxt->attr[i].attr == NULL)
4644 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
4646 ctxt->err = XML_SCHEMAS_ERR_ATTRUNKNOWN;
4648 if (ctxt->error != NULL)
4649 ctxt->error(ctxt->userData,
4650 "Attribute %s on %s is unknown\n",
4651 ctxt->attr[i].attr->name,
4659 * xmlSchemaValidateSimpleContent:
4660 * @ctxt: a schema validation context
4662 * @type: the type declaration
4664 * Validate the content of an element expected to be a simple type
4666 * Returns 0 if the element is schemas valid, a positive error code
4667 * number otherwise and -1 in case of internal or API error.
4670 xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
4671 xmlNodePtr node ATTRIBUTE_UNUSED) {
4673 xmlSchemaTypePtr type, base;
4681 * Validation Rule: Element Locally Valid (Type): 3.1.3
4683 value = xmlNodeGetContent(child);
4684 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
4685 switch (type->type) {
4686 case XML_SCHEMA_TYPE_RESTRICTION: {
4687 xmlSchemaFacetPtr facet;
4689 base = type->baseType;
4691 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4696 facet = type->facets;
4697 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
4711 * xmlSchemaValidateCheckNodeList
4712 * @nodelist: the list of nodes
4714 * Check the node list is only made of text nodes and entities pointing
4717 * Returns 1 if true, 0 if false and -1 in case of error
4720 xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist) {
4721 while (nodelist != NULL) {
4722 if (nodelist->type == XML_ENTITY_REF_NODE) {
4723 TODO /* implement recursion in the entity content */
4725 if ((nodelist->type != XML_TEXT_NODE) &&
4726 (nodelist->type != XML_COMMENT_NODE) &&
4727 (nodelist->type != XML_PI_NODE) &&
4728 (nodelist->type != XML_PI_NODE)) {
4731 nodelist = nodelist->next;
4737 * xmlSchemaSkipIgnored:
4738 * @ctxt: a schema validation context
4739 * @type: the current type context
4740 * @node: the top node.
4742 * Skip ignorable nodes in that context
4744 * Returns the new sibling
4745 * number otherwise and -1 in case of internal or API error.
4748 xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
4749 xmlSchemaTypePtr type,
4753 * TODO complete and handle entities
4755 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
4756 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
4757 while ((node != NULL) &&
4758 ((node->type == XML_COMMENT_NODE) ||
4759 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
4760 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
4761 (node->type == XML_TEXT_NODE) &&
4762 (IS_BLANK_NODE(node)))))) {
4769 * xmlSchemaValidateCallback:
4770 * @ctxt: a schema validation context
4771 * @name: the name of the element detected (might be NULL)
4774 * A transition has been made in the automata associated to an element
4778 xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
4779 const xmlChar *name ATTRIBUTE_UNUSED,
4780 xmlSchemaTypePtr type,
4782 xmlSchemaTypePtr oldtype = ctxt->type;
4783 xmlNodePtr oldnode = ctxt->node;
4784 #ifdef DEBUG_CONTENT
4785 xmlGenericError(xmlGenericErrorContext,
4786 "xmlSchemaValidateCallback: %s, %s, %s\n",
4787 name, type->name, node->name);
4791 xmlSchemaValidateContent(ctxt, node);
4792 ctxt->type = oldtype;
4793 ctxt->node = oldnode;
4799 * xmlSchemaValidateSimpleRestrictionType:
4800 * @ctxt: a schema validation context
4801 * @node: the top node.
4803 * Validate the content of a restriction type.
4805 * Returns 0 if the element is schemas valid, a positive error code
4806 * number otherwise and -1 in case of internal or API error.
4809 xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
4813 xmlSchemaTypePtr type;
4819 if ((ctxt == NULL) || (type == NULL)) {
4821 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4822 if (ctxt->error != NULL)
4823 ctxt->error(ctxt->userData,
4824 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
4829 * Only text and text based entities references shall be found there
4831 ret = xmlSchemaValidateCheckNodeList(child);
4834 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4835 if (ctxt->error != NULL)
4836 ctxt->error(ctxt->userData,
4837 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4840 } else if (ret == 0) {
4842 ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4843 if (ctxt->error != NULL)
4844 ctxt->error(ctxt->userData,
4845 "Element %s content is not a simple type\n",
4849 ctxt->type = type->subtypes;
4850 xmlSchemaValidateContent(ctxt, node);
4857 * xmlSchemaValidateSimpleType:
4858 * @ctxt: a schema validation context
4859 * @node: the top node.
4861 * Validate the content of an simple type.
4863 * Returns 0 if the element is schemas valid, a positive error code
4864 * number otherwise and -1 in case of internal or API error.
4867 xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4869 xmlSchemaTypePtr type;
4876 if ((ctxt == NULL) || (type == NULL)) {
4878 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4879 if (ctxt->error != NULL)
4880 ctxt->error(ctxt->userData,
4881 "Internal error: xmlSchemaValidateSimpleType %s\n",
4886 * Only text and text based entities references shall be found there
4888 ret = xmlSchemaValidateCheckNodeList(child);
4891 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4892 if (ctxt->error != NULL)
4893 ctxt->error(ctxt->userData,
4894 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4897 } else if (ret == 0) {
4899 ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4900 if (ctxt->error != NULL)
4901 ctxt->error(ctxt->userData,
4902 "Element %s content is not a simple type\n",
4907 * Validation Rule: Element Locally Valid (Type): 3.1.1
4909 attr = node->properties;
4910 while (attr != NULL) {
4911 if ((attr->ns == NULL) ||
4912 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
4913 ((!xmlStrEqual(attr->name, BAD_CAST"type")) &&
4914 (!xmlStrEqual(attr->name, BAD_CAST"nil")) &&
4915 (!xmlStrEqual(attr->name, BAD_CAST"schemasLocation")) &&
4916 (!xmlStrEqual(attr->name, BAD_CAST"noNamespaceSchemaLocation")))) {
4917 ctxt->err = XML_SCHEMAS_ERR_INVALIDATTR;
4919 if (ctxt->error != NULL)
4920 ctxt->error(ctxt->userData,
4921 "Element %s: attribute %s should not be present\n",
4922 node->name, attr->name);
4927 ctxt->type = type->subtypes;
4928 ret = xmlSchemaValidateSimpleContent(ctxt, node);
4934 * xmlSchemaValidateElementType:
4935 * @ctxt: a schema validation context
4936 * @node: the top node.
4938 * Validate the content of an element type.
4939 * Validation Rule: Element Locally Valid (Complex Type)
4941 * Returns 0 if the element is schemas valid, a positive error code
4942 * number otherwise and -1 in case of internal or API error.
4945 xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4947 xmlSchemaTypePtr type;
4948 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
4949 xmlSchemaElementPtr decl;
4952 oldregexp = ctxt->regexp;
4957 if ((ctxt == NULL) || (type == NULL)) {
4959 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4960 if (ctxt->error != NULL)
4961 ctxt->error(ctxt->userData,
4962 "Internal error: xmlSchemaValidateElementType\n",
4966 if (child == NULL) {
4967 if (type->minOccurs > 0) {
4969 ctxt->err = XML_SCHEMAS_ERR_MISSING;
4970 if (ctxt->error != NULL)
4971 ctxt->error(ctxt->userData,
4972 "Element %s: missing child %s\n",
4973 node->name, type->name);
4979 * Verify the element matches
4981 if (!xmlStrEqual(child->name, type->name)) {
4983 ctxt->err = XML_SCHEMAS_ERR_WRONGELEM;
4984 if (ctxt->error != NULL)
4985 ctxt->error(ctxt->userData,
4986 "Element %s: missing child %s found %s\n",
4987 node->name, type->name, child->name);
4991 * Verify the attributes
4993 attrBase = ctxt->attrBase;
4994 ctxt->attrBase = ctxt->attrNr;
4995 xmlSchemaRegisterAttributes(ctxt, child->properties);
4996 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
4998 * Verify the element content recursively
5000 decl = (xmlSchemaElementPtr) type;
5001 oldregexp = ctxt->regexp;
5002 if (decl->contModel != NULL) {
5003 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5004 (xmlRegExecCallbacks) xmlSchemaValidateCallback,
5006 #ifdef DEBUG_AUTOMATA
5007 xmlGenericError(xmlGenericErrorContext,
5008 "====> %s\n", node->name);
5011 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr)type,
5014 if (decl->contModel != NULL) {
5015 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
5016 #ifdef DEBUG_AUTOMATA
5017 xmlGenericError(xmlGenericErrorContext,
5018 "====> %s : %d\n", node->name, ret);
5022 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
5023 if (ctxt->error != NULL)
5024 ctxt->error(ctxt->userData, "Element %s content check failed\n",
5026 } else if (ret < 0) {
5028 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
5029 if (ctxt->error != NULL)
5030 ctxt->error(ctxt->userData, "Element %s content check failure\n",
5032 #ifdef DEBUG_CONTENT
5034 xmlGenericError(xmlGenericErrorContext,
5035 "Element %s content check succeeded\n", node->name);
5039 xmlRegFreeExecCtxt(ctxt->regexp);
5042 * Verify that all attributes were Schemas-validated
5044 xmlSchemaCheckAttributes(ctxt, node);
5045 ctxt->attrNr = ctxt->attrBase;
5046 ctxt->attrBase = attrBase;
5048 ctxt->regexp = oldregexp;
5056 * xmlSchemaValidateBasicType:
5057 * @ctxt: a schema validation context
5058 * @node: the top node.
5060 * Validate the content of an element expected to be a basic type type
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.
5066 xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
5068 xmlNodePtr child, cur;
5069 xmlSchemaTypePtr type;
5070 xmlChar *value; /* lexical representation */
5075 if ((ctxt == NULL) || (type == NULL)) {
5077 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
5078 if (ctxt->error != NULL)
5079 ctxt->error(ctxt->userData,
5080 "Internal error: xmlSchemaValidateBasicType\n",
5085 * First check the content model of the node.
5088 while (cur != NULL) {
5089 switch (cur->type) {
5091 case XML_CDATA_SECTION_NODE:
5093 case XML_COMMENT_NODE:
5094 case XML_XINCLUDE_START:
5095 case XML_XINCLUDE_END:
5097 case XML_ENTITY_REF_NODE:
5098 case XML_ENTITY_NODE:
5101 case XML_ELEMENT_NODE:
5103 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
5104 if (ctxt->error != NULL)
5105 ctxt->error(ctxt->userData,
5106 "Element %s: child %s should not be present\n",
5107 node->name, cur->name);
5109 case XML_ATTRIBUTE_NODE:
5110 case XML_DOCUMENT_NODE:
5111 case XML_DOCUMENT_TYPE_NODE:
5112 case XML_DOCUMENT_FRAG_NODE:
5113 case XML_NOTATION_NODE:
5114 case XML_HTML_DOCUMENT_NODE:
5116 case XML_ELEMENT_DECL:
5117 case XML_ATTRIBUTE_DECL:
5118 case XML_ENTITY_DECL:
5119 case XML_NAMESPACE_DECL:
5120 #ifdef LIBXML_DOCB_ENABLED
5121 case XML_DOCB_DOCUMENT_NODE:
5124 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
5125 if (ctxt->error != NULL)
5126 ctxt->error(ctxt->userData,
5127 "Element %s: node type %d unexpected here\n",
5128 node->name, cur->type);
5136 value = xmlNodeGetContent(child->parent);
5138 if (ctxt->value != NULL) {
5139 xmlSchemaFreeValue(ctxt->value);
5142 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5147 if (ctxt->error != NULL)
5148 ctxt->error(ctxt->userData,
5149 "Element %s: failed to validate basic type %s\n",
5150 node->name, type->name);
5151 ctxt->err = XML_SCHEMAS_ERR_VALUE;
5157 * xmlSchemaValidateComplexType:
5158 * @ctxt: a schema validation context
5159 * @node: the top node.
5161 * Validate the content of an element expected to be a complex type type
5162 * xmlschema-1.html#cvc-complex-type
5163 * Validation Rule: Element Locally Valid (Complex Type)
5165 * Returns 0 if the element is schemas valid, a positive error code
5166 * number otherwise and -1 in case of internal or API error.
5169 xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
5171 xmlSchemaTypePtr type, subtype;
5178 switch (type->contentType) {
5179 case XML_SCHEMA_CONTENT_EMPTY:
5180 if (child != NULL) {
5182 if (ctxt->error != NULL)
5183 ctxt->error(ctxt->userData,
5184 "Element %s is supposed to be empty\n",
5187 if (type->attributes != NULL) {
5188 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5190 subtype = type->subtypes;
5191 while (subtype != NULL) {
5192 ctxt->type = subtype;
5193 xmlSchemaValidateComplexType(ctxt, node);
5194 subtype = subtype->next;
5197 case XML_SCHEMA_CONTENT_ELEMENTS:
5198 case XML_SCHEMA_CONTENT_MIXED:
5199 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5201 * Skip ignorable nodes in that context
5203 child = xmlSchemaSkipIgnored(ctxt, type, child);
5204 while (child != NULL) {
5205 if (child->type == XML_ELEMENT_NODE) {
5206 ret = xmlRegExecPushString(ctxt->regexp,
5207 child->name, child);
5208 #ifdef DEBUG_AUTOMATA
5210 xmlGenericError(xmlGenericErrorContext,
5211 " --> %s Error\n", child->name);
5213 xmlGenericError(xmlGenericErrorContext,
5214 " --> %s\n", child->name);
5217 child = child->next;
5219 * Skip ignorable nodes in that context
5221 child = xmlSchemaSkipIgnored(ctxt, type, child);
5224 case XML_SCHEMA_CONTENT_BASIC: {
5225 if (type->subtypes != NULL) {
5226 ctxt->type = type->subtypes;
5227 xmlSchemaValidateComplexType(ctxt, node);
5229 if (type->baseType != NULL) {
5230 ctxt->type = type->baseType;
5231 xmlSchemaValidateBasicType(ctxt, node);
5233 if (type->attributes != NULL) {
5234 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5241 xmlGenericError(xmlGenericErrorContext,
5242 "unimplemented content type %d\n",
5249 * xmlSchemaValidateContent:
5250 * @ctxt: a schema validation context
5252 * @type: the type declaration
5254 * Validate the content of an element against the type.
5256 * Returns 0 if the element is schemas valid, a positive error code
5257 * number otherwise and -1 in case of internal or API error.
5260 xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
5262 xmlSchemaTypePtr type;
5268 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5271 switch (type->type) {
5272 case XML_SCHEMA_TYPE_ANY:
5273 /* Any type will do it, fine */
5274 TODO /* handle recursivity */
5276 case XML_SCHEMA_TYPE_COMPLEX:
5277 xmlSchemaValidateComplexType(ctxt, node);
5279 case XML_SCHEMA_TYPE_ELEMENT: {
5280 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5282 * Handle element reference here
5284 if (decl->ref != NULL) {
5285 if (decl->refDecl == NULL) {
5287 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
5288 if (ctxt->error != NULL)
5289 ctxt->error(ctxt->userData,
5290 "Internal error: element reference %s not resolved\n",
5294 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5295 decl = decl->refDecl;
5297 xmlSchemaValidateElementType(ctxt, node);
5301 case XML_SCHEMA_TYPE_BASIC:
5302 xmlSchemaValidateBasicType(ctxt, node);
5304 case XML_SCHEMA_TYPE_FACET:
5307 case XML_SCHEMA_TYPE_SIMPLE:
5308 xmlSchemaValidateSimpleType(ctxt, node);
5310 case XML_SCHEMA_TYPE_SEQUENCE:
5313 case XML_SCHEMA_TYPE_CHOICE:
5316 case XML_SCHEMA_TYPE_ALL:
5319 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5322 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5325 case XML_SCHEMA_TYPE_UR:
5328 case XML_SCHEMA_TYPE_RESTRICTION:
5329 /*xmlSchemaValidateRestrictionType(ctxt, node); */
5332 case XML_SCHEMA_TYPE_EXTENSION:
5335 case XML_SCHEMA_TYPE_ATTRIBUTE:
5338 case XML_SCHEMA_TYPE_GROUP:
5341 case XML_SCHEMA_TYPE_NOTATION:
5344 case XML_SCHEMA_TYPE_LIST:
5347 case XML_SCHEMA_TYPE_UNION:
5350 case XML_SCHEMA_FACET_MININCLUSIVE:
5353 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5356 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5359 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5362 case XML_SCHEMA_FACET_TOTALDIGITS:
5365 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5368 case XML_SCHEMA_FACET_PATTERN:
5371 case XML_SCHEMA_FACET_ENUMERATION:
5374 case XML_SCHEMA_FACET_WHITESPACE:
5377 case XML_SCHEMA_FACET_LENGTH:
5380 case XML_SCHEMA_FACET_MAXLENGTH:
5383 case XML_SCHEMA_FACET_MINLENGTH:
5386 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5390 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5392 if (ctxt->node == NULL)
5394 ctxt->node = ctxt->node->next;
5395 ctxt->type = type->next;
5400 * xmlSchemaValidateType:
5401 * @ctxt: a schema validation context
5403 * @type: the list of type declarations
5405 * Validate the content of an element against the types.
5407 * Returns 0 if the element is schemas valid, a positive error code
5408 * number otherwise and -1 in case of internal or API error.
5411 xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
5412 xmlSchemaElementPtr elemDecl,
5413 xmlSchemaTypePtr type) {
5416 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
5422 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
5424 ctxt->err = XML_SCHEMAS_ERR_ISABSTRACT;
5425 if (ctxt->error != NULL)
5426 ctxt->error(ctxt->userData, "Element %s is abstract\n", elem->name);
5432 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5433 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
5435 if (xmlStrEqual(nil, BAD_CAST "true")) {
5436 if (elem->children != NULL) {
5438 ctxt->err = XML_SCHEMAS_ERR_NOTEMPTY;
5439 if (ctxt->error != NULL)
5440 ctxt->error(ctxt->userData, "Element %s is not empty\n",
5444 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
5445 (elemDecl->value != NULL)) {
5447 ctxt->err = XML_SCHEMAS_ERR_HAVEDEFAULT;
5448 if (ctxt->error != NULL)
5449 ctxt->error(ctxt->userData,
5450 "Empty element %s cannot get a fixed value\n",
5458 ctxt->err = XML_SCHEMAS_ERR_NOTNILLABLE;
5460 if (ctxt->error != NULL)
5461 ctxt->error(ctxt->userData,
5462 "Element %s with xs:nil but not nillable\n",
5469 /* TODO 3.3.4: 4 if the element carries xs:type*/
5471 ctxt->type = elemDecl->subtypes;
5472 ctxt->node = elem->children;
5473 xmlSchemaValidateContent(ctxt, elem);
5474 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5481 * xmlSchemaValidateAttributes:
5482 * @ctxt: a schema validation context
5484 * @attributes: the list of attribute declarations
5486 * Validate the attributes of an element.
5488 * Returns 0 if the element is schemas valid, a positive error code
5489 * number otherwise and -1 in case of internal or API error.
5492 xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
5493 xmlSchemaAttributePtr attributes) {
5497 xmlSchemaAttributeGroupPtr group = NULL;
5499 if (attributes == NULL)
5501 while (attributes != NULL) {
5503 * Handle attribute groups
5505 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5506 group = (xmlSchemaAttributeGroupPtr) attributes;
5507 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
5508 attributes = group->next;
5511 for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
5512 attr = ctxt->attr[i].attr;
5515 if (attributes->ref != NULL) {
5516 if (!xmlStrEqual(attr->name, attributes->ref))
5518 if (attr->ns != NULL) {
5519 if ((attributes->refNs == NULL) ||
5520 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
5522 } else if (attributes->refNs != NULL) {
5526 if (!xmlStrEqual(attr->name, attributes->name))
5529 * TODO: handle the mess about namespaces here.
5531 if ((attr->ns != NULL) /* || (attributes->ns != NULL) */) {
5535 ctxt->cur = (xmlNodePtr) attributes;
5536 if (attributes->subtypes == NULL) {
5538 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
5539 if (ctxt->error != NULL)
5540 ctxt->error(ctxt->userData,
5541 "Internal error: attribute %s type not resolved\n",
5545 value = xmlNodeListGetString(elem->doc, attr->children, 1);
5546 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
5550 ctxt->err = XML_SCHEMAS_ERR_ATTRINVALID;
5551 if (ctxt->error != NULL)
5552 ctxt->error(ctxt->userData,
5553 "attribute %s on %s does not match type\n",
5554 attr->name, elem->name);
5556 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
5558 if (value != NULL) {
5562 attributes = attributes->next;
5568 * xmlSchemaValidateElement:
5569 * @ctxt: a schema validation context
5572 * Validate an element in a tree
5574 * Returns 0 if the element is schemas valid, a positive error code
5575 * number otherwise and -1 in case of internal or API error.
5578 xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem) {
5579 xmlSchemaElementPtr elemDecl;
5582 if (elem->ns != NULL)
5583 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5584 elem->name, elem->ns->href, NULL);
5586 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5587 elem->name, NULL, NULL);
5591 if (elemDecl == NULL) {
5593 ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
5594 if (ctxt->error != NULL)
5595 ctxt->error(ctxt->userData, "Element %s not declared\n",
5599 if (elemDecl->subtypes == NULL) {
5601 ctxt->err = XML_SCHEMAS_ERR_NOTYPE;
5602 if (ctxt->error != NULL)
5603 ctxt->error(ctxt->userData, "Element %s has no type\n",
5608 * Verify the attributes
5610 attrBase = ctxt->attrBase;
5611 ctxt->attrBase = ctxt->attrNr;
5612 xmlSchemaRegisterAttributes(ctxt, elem->properties);
5613 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5615 * Verify the element content recursively
5617 if (elemDecl->contModel != NULL) {
5618 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
5619 (xmlRegExecCallbacks) xmlSchemaValidateCallback,
5621 #ifdef DEBUG_AUTOMATA
5622 xmlGenericError(xmlGenericErrorContext,
5623 "====> %s\n", elem->name);
5626 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
5627 if (elemDecl->contModel != NULL) {
5628 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
5629 #ifdef DEBUG_AUTOMATA
5630 xmlGenericError(xmlGenericErrorContext,
5631 "====> %s : %d\n", elem->name, ret);
5634 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
5636 if (ctxt->error != NULL)
5637 ctxt->error(ctxt->userData, "Element %s content check failed\n",
5639 } else if (ret < 0) {
5640 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
5642 if (ctxt->error != NULL)
5643 ctxt->error(ctxt->userData, "Element %s content check failed\n",
5645 #ifdef DEBUG_CONTENT
5647 xmlGenericError(xmlGenericErrorContext,
5648 "Element %s content check succeeded\n", elem->name);
5652 xmlRegFreeExecCtxt(ctxt->regexp);
5655 * Verify that all attributes were Schemas-validated
5657 xmlSchemaCheckAttributes(ctxt, elem);
5658 ctxt->attrNr = ctxt->attrBase;
5659 ctxt->attrBase = attrBase;
5665 * xmlSchemaValidateDocument:
5666 * @ctxt: a schema validation context
5667 * @doc: a parsed document tree
5669 * Validate a document tree in memory.
5671 * Returns 0 if the document is schemas valid, a positive error code
5672 * number otherwise and -1 in case of internal or API error.
5675 xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5677 xmlSchemaElementPtr elemDecl;
5679 root = xmlDocGetRootElement(doc);
5681 ctxt->err = XML_SCHEMAS_ERR_NOROOT;
5683 if (ctxt->error != NULL)
5684 ctxt->error(ctxt->userData, "document has no root\n");
5687 if (root->ns != NULL)
5688 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5689 root->name, root->ns->href, NULL);
5691 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5692 root->name, NULL, NULL);
5693 if (elemDecl == NULL) {
5694 ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
5696 if (ctxt->error != NULL)
5697 ctxt->error(ctxt->userData, "Element %s not declared\n",
5699 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
5700 ctxt->err = XML_SCHEMAS_ERR_NOTTOPLEVEL;
5702 if (ctxt->error != NULL)
5703 ctxt->error(ctxt->userData, "Root element %s not toplevel\n",
5707 * Okay, start the recursive validation
5709 xmlSchemaValidateElement(ctxt, root);
5714 /************************************************************************
5716 * SAX Validation code *
5718 ************************************************************************/
5720 /************************************************************************
5722 * Validation interfaces *
5724 ************************************************************************/
5727 * xmlSchemaNewValidCtxt:
5728 * @schema: a precompiled XML Schemas
5730 * Create an XML Schemas validation context based on the given schema
5732 * Returns the validation context or NULL in case of error
5734 xmlSchemaValidCtxtPtr
5735 xmlSchemaNewValidCtxt(xmlSchemaPtr schema) {
5736 xmlSchemaValidCtxtPtr ret;
5738 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
5740 xmlGenericError(xmlGenericErrorContext,
5741 "Failed to allocate new schama validation context\n");
5744 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
5745 ret->schema = schema;
5748 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
5749 sizeof(xmlSchemaAttrState));
5750 if (ret->attr == NULL) {
5754 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
5759 * xmlSchemaFreeValidCtxt:
5760 * @ctxt: the schema validation context
5762 * Free the resources associated to the schema validation context
5765 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) {
5768 if (ctxt->attr != NULL)
5769 xmlFree(ctxt->attr);
5770 if (ctxt->value != NULL)
5771 xmlSchemaFreeValue(ctxt->value);
5776 * xmlSchemaSetValidErrors:
5777 * @ctxt: a schema validation context
5778 * @err: the error function
5779 * @warn: the warning function
5780 * @ctx: the functions context
5782 * Set the error and warning callback informations
5785 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
5786 xmlSchemaValidityErrorFunc err,
5787 xmlSchemaValidityWarningFunc warn, void *ctx) {
5791 ctxt->warning = warn;
5792 ctxt->userData = ctx;
5796 * xmlSchemaValidateDoc:
5797 * @ctxt: a schema validation context
5798 * @doc: a parsed document tree
5800 * Validate a document tree in memory.
5802 * Returns 0 if the document is schemas valid, a positive error code
5803 * number otherwise and -1 in case of internal or API error.
5806 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5809 if ((ctxt == NULL) || (doc == NULL))
5813 ret = xmlSchemaValidateDocument(ctxt, doc);
5818 * xmlSchemaValidateStream:
5819 * @ctxt: a schema validation context
5820 * @input: the input to use for reading the data
5821 * @enc: an optional encoding information
5822 * @sax: a SAX handler for the resulting events
5823 * @user_data: the context to provide to the SAX handler.
5825 * Validate a document tree in memory.
5827 * Returns 0 if the document is schemas valid, a positive error code
5828 * number otherwise and -1 in case of internal or API error.
5831 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
5832 xmlParserInputBufferPtr input, xmlCharEncoding enc,
5833 xmlSAXHandlerPtr sax, void *user_data) {
5834 if ((ctxt == NULL) || (input == NULL))
5836 ctxt->input = input;
5839 ctxt->user_data = user_data;
5844 #endif /* LIBXML_SCHEMAS_ENABLED */