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