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