blob: 3a96b635c6136ed85b2f0217c7a3a4e86439f925 [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")) {
Daniel Veillarddecd64d2002-04-18 14:41:51 +00002679 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002680 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
Daniel Veillard4255d502002-04-16 15:50:10 +00003088 if (elem->contModel != NULL)
3089 return;
3090 if (elem->subtypes == NULL)
3091 return;
3092 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
3093 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003094 if (elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC)
3095 return;
3096
3097#ifdef DEBUG_CONTENT
3098 xmlGenericError(xmlGenericErrorContext,
3099 "Building content model for %s\n", name);
3100#endif
3101
Daniel Veillard4255d502002-04-16 15:50:10 +00003102 ctxt->am = xmlNewAutomata();
3103 if (ctxt->am == NULL) {
3104 xmlGenericError(xmlGenericErrorContext,
3105 "Cannot create automata for elem %s\n", name);
3106 return;
3107 }
3108 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3109 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3110 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
3111 elem->contModel = xmlAutomataCompile(ctxt->am);
3112#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00003113 xmlGenericError(xmlGenericErrorContext,
3114 "Content model of %s:\n", name);
3115 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003116#endif
3117 ctxt->state = NULL;
3118 xmlFreeAutomata(ctxt->am);
3119 ctxt->am = NULL;
3120}
3121
3122/**
3123 * xmlSchemaRefFixupCallback:
3124 * @elem: the schema element context
3125 * @ctxt: the schema parser context
3126 *
3127 * Free the resources associated to the schema parser context
3128 */
3129static void
3130xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
3131 xmlSchemaParserCtxtPtr ctxt,
3132 const xmlChar *name,
3133 ATTRIBUTE_UNUSED const xmlChar *context,
3134 ATTRIBUTE_UNUSED const xmlChar *namespace)
3135{
3136 if ((ctxt == NULL) || (elem == NULL))
3137 return;
3138 if (elem->ref != NULL) {
3139 xmlSchemaElementPtr elemDecl;
3140
3141 if (elem->subtypes != NULL) {
3142 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3143 if ((ctxt != NULL) && (ctxt->error != NULL))
3144 ctxt->error(ctxt->userData,
3145 "Schemas: element %s have both ref and subtype\n",
3146 name);
3147 return;
3148 }
3149 elemDecl = xmlHashLookup2(ctxt->schema->elemDecl,
3150 elem->ref, elem->refNs);
3151
3152 if (elemDecl == NULL) {
3153 if ((ctxt != NULL) && (ctxt->error != NULL))
3154 ctxt->error(ctxt->userData,
3155 "Schemas: element %s ref to %s not found\n",
3156 name, elem->ref);
3157 return;
3158 }
3159 elem->refDecl = elemDecl;
3160 } else if (elem->namedType != NULL) {
3161 xmlSchemaTypePtr typeDecl;
3162
3163 if (elem->subtypes != NULL) {
3164 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3165 if ((ctxt != NULL) && (ctxt->error != NULL))
3166 ctxt->error(ctxt->userData,
3167 "Schemas: element %s have both type and subtype\n",
3168 name);
3169 return;
3170 }
3171 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3172 elem->namedTypeNs);
3173
3174 if (typeDecl == NULL) {
3175 if ((ctxt != NULL) && (ctxt->error != NULL))
3176 ctxt->error(ctxt->userData,
3177 "Schemas: element %s type %s not found\n",
3178 name, elem->namedType);
3179 return;
3180 }
3181 elem->subtypes = typeDecl;
3182 }
3183}
3184
3185/**
3186 * xmlSchemaTypeFixup:
3187 * @typeDecl: the schema type definition
3188 * @ctxt: the schema parser context
3189 *
3190 * Fixes the content model of the type.
3191 */
3192static void
3193xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
3194 xmlSchemaParserCtxtPtr ctxt,
3195 const xmlChar *name)
3196{
3197 if (name == NULL)
3198 name = typeDecl->name;
3199 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
3200 switch (typeDecl->type) {
3201 case XML_SCHEMA_TYPE_SIMPLE_CONTENT: {
3202 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3203 typeDecl->contentType = typeDecl->subtypes->contentType;
3204 break;
3205 }
3206 case XML_SCHEMA_TYPE_RESTRICTION: {
3207 if (typeDecl->subtypes != NULL)
3208 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3209
3210 if (typeDecl->base != NULL) {
3211 xmlSchemaTypePtr baseType;
3212
3213 baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3214 typeDecl->baseNs);
3215 if (baseType == NULL) {
3216 if ((ctxt != NULL) && (ctxt->error != NULL))
3217 ctxt->error(ctxt->userData,
3218 "Schemas: type %s base type %s not found\n",
3219 name, typeDecl->base);
3220 }
3221 typeDecl->baseType = baseType;
3222 }
3223 if (typeDecl->subtypes == NULL)
3224 /* 1.1.1 */
3225 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3226 else if ((typeDecl->subtypes->subtypes == NULL) &&
3227 ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3228 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3229 /* 1.1.2 */
3230 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3231 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3232 (typeDecl->subtypes->subtypes == NULL))
3233 /* 1.1.3 */
3234 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3235 else {
3236 /* 1.2 and 2.X are applied at the other layer */
3237 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3238 }
3239 break;
3240 }
3241 case XML_SCHEMA_TYPE_EXTENSION: {
3242 xmlSchemaContentType explicitContentType;
3243 xmlSchemaTypePtr base;
3244
3245 if (typeDecl->base != NULL) {
3246 xmlSchemaTypePtr baseType;
3247
3248 baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3249 typeDecl->baseNs);
3250 if (baseType == NULL) {
3251 if ((ctxt != NULL) && (ctxt->error != NULL))
3252 ctxt->error(ctxt->userData,
3253 "Schemas: type %s base type %s not found\n",
3254 name, typeDecl->base);
3255 }
3256 typeDecl->baseType = baseType;
3257 }
3258 if (typeDecl->subtypes != NULL)
3259 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3260
Daniel Veillard8651f532002-04-17 09:06:27 +00003261 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillard4255d502002-04-16 15:50:10 +00003262 if (typeDecl->subtypes == NULL)
3263 /* 1.1.1 */
3264 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3265 else if ((typeDecl->subtypes->subtypes == NULL) &&
3266 ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3267 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3268 /* 1.1.2 */
3269 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3270 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3271 (typeDecl->subtypes->subtypes == NULL))
3272 /* 1.1.3 */
3273 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3274
3275 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3276 typeDecl->baseNs);
3277 if (base == NULL) {
3278 xmlSchemaErrorContext(ctxt, NULL, typeDecl->node, NULL);
3279 if ((ctxt != NULL) && (ctxt->error != NULL))
3280 ctxt->error(ctxt->userData,
3281 "Schemas: base type %s of type %s not found\n",
3282 typeDecl->base, name);
3283 return;
3284 }
3285 xmlSchemaTypeFixup(base, ctxt, NULL);
3286 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
3287 /* 2.1 */
3288 typeDecl->contentType = base->contentType;
3289 } else if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
3290 /* 2.2 imbitable ! */
3291 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3292 } else {
3293 /* 2.3 imbitable pareil ! */
3294 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3295 }
3296 break;
3297 }
3298 case XML_SCHEMA_TYPE_COMPLEX: {
3299 if (typeDecl->subtypes == NULL) {
3300 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3301 } else {
3302 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3303 typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3304 else {
3305 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3306 typeDecl->contentType = typeDecl->subtypes->contentType;
3307 }
3308 }
3309 break;
3310 }
3311 case XML_SCHEMA_TYPE_COMPLEX_CONTENT: {
3312 if (typeDecl->subtypes == NULL) {
3313 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3314 } else {
3315 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3316 typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3317 else {
3318 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3319 typeDecl->contentType = typeDecl->subtypes->contentType;
3320 }
3321 }
3322 break;
3323 }
3324 case XML_SCHEMA_TYPE_SEQUENCE:
3325 case XML_SCHEMA_TYPE_GROUP:
3326 case XML_SCHEMA_TYPE_ALL:
3327 case XML_SCHEMA_TYPE_CHOICE:
3328 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3329 break;
3330 case XML_SCHEMA_TYPE_BASIC:
3331 case XML_SCHEMA_TYPE_ANY:
3332 case XML_SCHEMA_TYPE_FACET:
3333 case XML_SCHEMA_TYPE_SIMPLE:
3334 case XML_SCHEMA_TYPE_UR:
3335 case XML_SCHEMA_TYPE_ELEMENT:
3336 case XML_SCHEMA_TYPE_ATTRIBUTE:
3337 case XML_SCHEMA_TYPE_NOTATION:
3338 case XML_SCHEMA_TYPE_LIST:
3339 case XML_SCHEMA_TYPE_UNION:
3340 case XML_SCHEMA_FACET_MININCLUSIVE:
3341 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3342 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3343 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
3344 case XML_SCHEMA_FACET_TOTALDIGITS:
3345 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3346 case XML_SCHEMA_FACET_PATTERN:
3347 case XML_SCHEMA_FACET_ENUMERATION:
3348 case XML_SCHEMA_FACET_WHITESPACE:
3349 case XML_SCHEMA_FACET_LENGTH:
3350 case XML_SCHEMA_FACET_MAXLENGTH:
3351 case XML_SCHEMA_FACET_MINLENGTH:
3352 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
3353 break;
3354 }
3355 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003356#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003357 if (typeDecl->node != NULL) {
3358 xmlGenericError(xmlGenericErrorContext,
3359 "Type of %s : %s:%d :", name, typeDecl->node->doc->URL,
3360 xmlGetLineNo(typeDecl->node));
3361 } else {
3362 xmlGenericError(xmlGenericErrorContext,
3363 "Type of %s :", name);
3364 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003365 switch (typeDecl->contentType) {
3366 case XML_SCHEMA_CONTENT_SIMPLE:
3367 xmlGenericError(xmlGenericErrorContext,
3368 "simple\n"); break;
3369 case XML_SCHEMA_CONTENT_ELEMENTS:
3370 xmlGenericError(xmlGenericErrorContext,
3371 "elements\n"); break;
3372 case XML_SCHEMA_CONTENT_UNKNOWN:
3373 xmlGenericError(xmlGenericErrorContext,
3374 "unknown !!!\n"); break;
3375 case XML_SCHEMA_CONTENT_EMPTY:
3376 xmlGenericError(xmlGenericErrorContext,
3377 "empty\n"); break;
3378 case XML_SCHEMA_CONTENT_MIXED:
3379 xmlGenericError(xmlGenericErrorContext,
3380 "mixed\n"); break;
3381 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
3382 xmlGenericError(xmlGenericErrorContext,
3383 "mixed or elems\n"); break;
3384 case XML_SCHEMA_CONTENT_BASIC:
3385 xmlGenericError(xmlGenericErrorContext,
3386 "basic\n"); break;
3387 default:
3388 xmlGenericError(xmlGenericErrorContext,
3389 "not registered !!!\n"); break;
3390 }
3391#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003392}
3393
3394/**
3395 * xmlSchemaCheckDefaults:
3396 * @typeDecl: the schema type definition
3397 * @ctxt: the schema parser context
3398 *
3399 * Checks the default values types, especially for facets
3400 */
3401static void
3402xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
3403 xmlSchemaParserCtxtPtr ctxt,
3404 const xmlChar *name)
3405{
3406 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
3407 if (name == NULL)
3408 name = typeDecl->name;
3409 if (nonNegativeIntegerType == NULL) {
3410 nonNegativeIntegerType = xmlSchemaGetPredefinedType(
3411 BAD_CAST "nonNegativeInteger", xmlSchemaNs);
3412 }
3413 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
3414 if (typeDecl->facets != NULL) {
3415 xmlSchemaFacetPtr facet = typeDecl->facets;
3416 while (facet != NULL) {
3417 switch (facet->type) {
3418 case XML_SCHEMA_FACET_MININCLUSIVE:
3419 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3420 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3421 case XML_SCHEMA_FACET_MAXEXCLUSIVE: {
3422 /*
3423 * Okay we need to validate the value
3424 * at that point.
3425 */
3426 xmlSchemaValidCtxtPtr vctxt;
3427
3428 vctxt = xmlSchemaNewValidCtxt(NULL);
3429 if (vctxt == NULL)
3430 break;
3431 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3432 facet->value);
3433 facet->val = vctxt->value;
3434 vctxt->value = NULL;
3435 if (facet->val == NULL) {
3436 /* error code */
3437 xmlSchemaErrorContext(ctxt, NULL,
3438 facet->node, NULL);
3439 ctxt->error(ctxt->userData,
3440 "Schemas: type %s facet value %s invalid\n",
3441 name, facet->value);
3442 }
3443 xmlSchemaFreeValidCtxt(vctxt);
3444 break;
3445 }
3446 case XML_SCHEMA_FACET_ENUMERATION: {
3447 /*
3448 * Okay we need to validate the value
3449 * at that point.
3450 */
3451 xmlSchemaValidCtxtPtr vctxt;
3452 int ret;
3453
3454 vctxt = xmlSchemaNewValidCtxt(NULL);
3455 if (vctxt == NULL)
3456 break;
3457 ret = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3458 facet->value);
3459 if (ret != 0) {
3460 xmlSchemaErrorContext(ctxt, NULL,
3461 facet->node, NULL);
3462 ctxt->error(ctxt->userData,
3463 "Schemas: type %s enumeration value %s invalid\n",
3464 name, facet->value);
3465 }
3466 xmlSchemaFreeValidCtxt(vctxt);
3467 break;
3468 }
3469 case XML_SCHEMA_FACET_PATTERN:
3470 facet->regexp = xmlRegexpCompile(facet->value);
3471 if (facet->regexp == NULL) {
3472 /* error code */
3473 ctxt->error(ctxt->userData,
3474 "Schemas: type %s facet regexp %s invalid\n",
3475 name, facet->value);
3476 }
3477 break;
3478 case XML_SCHEMA_FACET_TOTALDIGITS:
3479 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3480 case XML_SCHEMA_FACET_LENGTH:
3481 case XML_SCHEMA_FACET_MAXLENGTH:
3482 case XML_SCHEMA_FACET_MINLENGTH: {
3483 int ret;
3484
3485 ret = xmlSchemaValidatePredefinedType(
3486 nonNegativeIntegerType, facet->value,
3487 &facet->val);
3488 if (ret != 0) {
3489 /* error code */
3490 xmlSchemaErrorContext(ctxt, NULL,
3491 facet->node, NULL);
3492 ctxt->error(ctxt->userData,
3493 "Schemas: type %s facet value %s invalid\n",
3494 name, facet->value);
3495 }
3496 break;
3497 }
3498 case XML_SCHEMA_FACET_WHITESPACE: {
3499 if (xmlStrEqual(facet->value, BAD_CAST"preserve")) {
3500 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
3501 } else if (xmlStrEqual(facet->value,
3502 BAD_CAST"replace")) {
3503 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
3504 } else if (xmlStrEqual(facet->value,
3505 BAD_CAST"collapse")) {
3506 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
3507 } else {
3508 xmlSchemaErrorContext(ctxt, NULL,
3509 facet->node, NULL);
3510 ctxt->error(ctxt->userData,
3511 "Schemas: type %s whiteSpace value %s invalid\n",
3512 name, facet->value);
3513 }
3514 }
3515 default:
3516 break;
3517 }
3518 facet = facet->next;
3519 }
3520 }
3521 }
3522}
3523
3524/**
3525 * xmlSchemaAttrFixup:
3526 * @attrDecl: the schema attribute definition
3527 * @ctxt: the schema parser context
3528 * @name: the attribute name
3529 *
3530 * Fixes finish doing the computations on the attributes definitions
3531 */
3532static void
3533xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
3534 xmlSchemaParserCtxtPtr ctxt,
3535 const xmlChar *name)
3536{
3537 if (name == NULL)
3538 name = attrDecl->name;
3539 if (attrDecl->subtypes != NULL)
3540 return;
3541 if (attrDecl->typeName != NULL) {
3542 xmlSchemaTypePtr type;
3543
3544 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
3545 attrDecl->typeNs);
3546 if (type == NULL) {
3547 if ((ctxt != NULL) && (ctxt->error != NULL))
3548 ctxt->error(ctxt->userData,
3549 "Schemas: attribute %s type %s not found\n",
3550 name, attrDecl->typeName);
3551 }
3552 attrDecl->subtypes = type;
3553 } else if (attrDecl->ref != NULL) {
3554 xmlSchemaAttributePtr ref;
3555
3556 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
3557 attrDecl->refNs);
3558 if (ref == NULL) {
3559 if ((ctxt != NULL) && (ctxt->error != NULL))
3560 ctxt->error(ctxt->userData,
3561 "Schemas: attribute %s reference %s not found\n",
3562 name, attrDecl->ref);
3563 return;
3564 }
3565 xmlSchemaAttrFixup(ref, ctxt, NULL);
3566 attrDecl->subtypes = ref->subtypes;
3567 } else {
3568 if ((ctxt != NULL) && (ctxt->error != NULL))
3569 ctxt->error(ctxt->userData,
3570 "Schemas: attribute %s has no type nor reference\n",
3571 name);
3572 }
3573}
3574
3575/**
3576 * xmlSchemaParse:
3577 * @ctxt: a schema validation context
3578 * @URL: the location of the schema
3579 *
3580 * Load, XML parse a schema definition resource and build an internal
3581 * XML Shema struture which can be used to validate instances.
3582 * *WARNING* this interface is highly subject to change
3583 *
3584 * Returns the internal XML Schema structure built from the resource or
3585 * NULL in case of error
3586 */
3587xmlSchemaPtr
3588xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
3589{
3590 xmlSchemaPtr ret = NULL;
3591 xmlDocPtr doc;
3592 xmlNodePtr root, cur, delete;
3593
3594 xmlSchemaInitTypes();
3595
3596 if ((ctxt == NULL) || (ctxt->URL == NULL))
3597 return (NULL);
3598
3599 ctxt->counter = 0;
3600 ctxt->container = NULL;
3601
3602 /*
3603 * First step is to parse the input document into an DOM/Infoset
3604 */
3605 doc = xmlParseFile((const char *) ctxt->URL);
3606 if (doc == NULL) {
3607 if (ctxt->error != NULL)
3608 ctxt->error(ctxt->userData,
3609 "xmlSchemaParse: could not load %s\n", ctxt->URL);
3610 return (NULL);
3611 }
3612
3613 /*
3614 * Then extract the root and Schema parse it
3615 */
3616 root = xmlDocGetRootElement(doc);
3617 if (root == NULL) {
3618 if (ctxt->error != NULL)
3619 ctxt->error(ctxt->userData, "xmlSchemaParse: %s is empty\n",
3620 ctxt->URL);
3621 return (NULL);
3622 }
3623
3624 /*
3625 * Remove all the blank text nodes
3626 */
3627 delete = NULL;
3628 cur = root;
3629 while (cur != NULL) {
3630 if (delete != NULL) {
3631 xmlUnlinkNode(delete);
3632 xmlFreeNode(delete);
3633 delete = NULL;
3634 }
3635 if (cur->type == XML_TEXT_NODE) {
3636 if (IS_BLANK_NODE(cur)) {
3637 if (xmlNodeGetSpacePreserve(cur) != 1) {
3638 delete = cur;
3639 }
3640 }
3641 } else if ((cur->type != XML_ELEMENT_NODE) &&
3642 (cur->type != XML_CDATA_SECTION_NODE)) {
3643 delete = cur;
3644 goto skip_children;
3645 }
3646
3647 /*
3648 * Skip to next node
3649 */
3650 if (cur->children != NULL) {
3651 if ((cur->children->type != XML_ENTITY_DECL) &&
3652 (cur->children->type != XML_ENTITY_REF_NODE) &&
3653 (cur->children->type != XML_ENTITY_NODE)) {
3654 cur = cur->children;
3655 continue;
3656 }
3657 }
3658skip_children:
3659 if (cur->next != NULL) {
3660 cur = cur->next;
3661 continue;
3662 }
3663
3664 do {
3665 cur = cur->parent;
3666 if (cur == NULL)
3667 break;
3668 if (cur == root) {
3669 cur = NULL;
3670 break;
3671 }
3672 if (cur->next != NULL) {
3673 cur = cur->next;
3674 break;
3675 }
3676 } while (cur != NULL);
3677 }
3678 if (delete != NULL) {
3679 xmlUnlinkNode(delete);
3680 xmlFreeNode(delete);
3681 delete = NULL;
3682 }
3683
3684 /*
3685 * Then do the parsing for good
3686 */
3687 ret = xmlSchemaParseSchema(ctxt, root);
3688 ret->doc = doc;
3689
3690 /*
3691 * Then fix all the references.
3692 */
3693 ctxt->schema = ret;
3694 xmlHashScanFull(ret->elemDecl,
3695 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
3696
3697 /*
3698 * Then fixup all types properties
3699 */
3700 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
3701
3702 /*
3703 * Then build the content model for all elements
3704 */
3705 xmlHashScan(ret->elemDecl,
3706 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
3707
3708 /*
3709 * Then check the defaults part of the type like facets values
3710 */
3711 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt);
3712
3713 /*
3714 * Then fixup all attributes declarations
3715 */
3716 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
3717
3718 return (ret);
3719}
3720
3721/**
3722 * xmlSchemaParse:
3723 * @ctxt: a schema validation context
3724 * @URL: the location of the schema
3725 *
3726 * Load, XML parse a schema definition resource and build an internal
3727 * XML Shema struture which can be used to validate instances.
3728 * *WARNING* this interface is highly subject to change
3729 *
3730 * Returns the internal XML Schema structure built from the resource or
3731 * NULL in case of error
3732 */
3733void
3734xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
3735 xmlSchemaValidityErrorFunc err,
3736 xmlSchemaValidityWarningFunc warn, void *ctx) {
3737 if (ctxt == NULL)
3738 return;
3739 ctxt->error = err;
3740 ctxt->warning = warn;
3741 ctxt->userData = ctx;
3742}
3743
3744/************************************************************************
3745 * *
3746 * Simple type validation *
3747 * *
3748 ************************************************************************/
3749
3750/**
3751 * xmlSchemaValidateSimpleValue:
3752 * @ctxt: a schema validation context
3753 * @type: the type declaration
3754 * @value: the value to validate
3755 *
3756 * Validate a value against a simple type
3757 *
3758 * Returns 0 if the value is valid, a positive error code
3759 * number otherwise and -1 in case of internal or API error.
3760 */
3761static int
3762xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
3763 xmlSchemaTypePtr type,
3764 xmlChar *value) {
3765 int ret = 0;
3766 /*
3767 * First normalize the value accordingly to Schema Datatype
3768 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
3769 */
3770 /*
3771 * Then check the normalized value against the lexical space of the
3772 * type.
3773 */
3774 if (type->type == XML_SCHEMA_TYPE_BASIC) {
3775 if (ctxt->value != NULL) {
3776 xmlSchemaFreeValue(ctxt->value);
3777 ctxt->value = NULL;
3778 }
3779 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
3780 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
3781 xmlSchemaTypePtr base;
3782 xmlSchemaFacetPtr facet;
3783 int tmp;
3784
3785 base = type->baseType;
3786 if (base != NULL) {
3787 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
3788 } else if (type->subtypes != NULL) {
3789
3790 }
3791 /*
3792 * Do not validate facets when working on building the Schemas
3793 */
3794 if (ctxt->schema != NULL) {
3795 if (ret == 0) {
3796 facet = type->facets;
3797 while (facet != NULL) {
3798 tmp = xmlSchemaValidateFacet(base, facet, value,
3799 ctxt->value);
3800 if (tmp != 0)
3801 ret = tmp;
3802 facet = facet->next;
3803 }
3804 }
3805 }
3806 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
3807 xmlSchemaTypePtr base;
3808
3809 base = type->subtypes;
3810 if (base != NULL) {
3811 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
3812 } else {
3813 TODO
3814 }
3815 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
3816 xmlSchemaTypePtr base;
3817 xmlChar *cur, *end, tmp;
3818 int ret2;
3819
3820 base = type->subtypes;
3821 if (base == NULL) {
3822 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
3823 if (ctxt->error != NULL) {
3824 xmlSchemaErrorContext(NULL, ctxt->schema, type->node, NULL);
3825 ctxt->error(ctxt->userData,
3826 "Internal: List type %s has no base type\n",
3827 type->name);
3828 }
3829 return(-1);
3830 }
3831 cur = value;
3832 do {
3833 while (IS_BLANK(*cur)) cur++;
3834 end = cur;
3835 while ((*end != 0) && (!(IS_BLANK(*end)))) end++;
3836 if (end == cur)
3837 break;
3838 tmp = *end;
3839 *end = 0;
3840 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, cur);
3841 if (ret2 != 0)
3842 ret = 1;
3843 *end = tmp;
3844 cur = end;
3845 } while (*cur != 0);
3846 } else {
3847 TODO
3848 }
3849 return(ret);
3850}
3851
3852/************************************************************************
3853 * *
3854 * DOM Validation code *
3855 * *
3856 ************************************************************************/
3857
3858static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
3859 xmlNodePtr node);
3860static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
3861 xmlNodePtr elem, xmlSchemaAttributePtr attributes);
3862static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
3863 xmlNodePtr elem, xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type);
3864
3865/**
3866 * xmlSchemaRegisterAttributes:
3867 * @ctxt: a schema validation context
3868 * @attrs: a list of attributes
3869 *
3870 * Register the list of attributes as the set to be validated on that element
3871 *
3872 * Returns -1 in case of error, 0 otherwise
3873 */
3874static int
3875xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt,
3876 xmlAttrPtr attrs) {
3877 while (attrs != NULL) {
3878 if (ctxt->attrNr >= ctxt->attrMax) {
3879 xmlSchemaAttrStatePtr tmp;
3880
3881 ctxt->attrMax *= 2;
3882 tmp = (xmlSchemaAttrStatePtr)
3883 xmlRealloc(ctxt->attr, ctxt->attrMax *
3884 sizeof(xmlSchemaAttrState));
3885 if (tmp == NULL) {
3886 ctxt->attrMax /= 2;
3887 return(-1);
3888 }
3889 ctxt->attr = tmp;
3890 }
3891 ctxt->attr[ctxt->attrNr].attr = attrs;
3892 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
3893 ctxt->attrNr++;
3894 attrs = attrs->next;
3895 }
3896 return(0);
3897}
3898
3899/**
3900 * xmlSchemaCheckAttributes:
3901 * @ctxt: a schema validation context
3902 * @node: the node carrying it.
3903 *
3904 * Check that the registered set of attributes on the current node
3905 * has been properly validated.
3906 *
3907 * Returns 0 if validity constraints are met, 1 otherwise.
3908 */
3909static int
3910xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
3911 int ret = 0;
3912 int i;
3913
3914 for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
3915 if (ctxt->attr[i].attr == NULL)
3916 break;
3917 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
3918 ret = 1;
3919 ctxt->err = XML_SCHEMAS_ERR_ATTRUNKNOWN;
3920 if (ctxt->error != NULL)
3921 ctxt->error(ctxt->userData,
3922 "Attribute %s on %s is unknown\n",
3923 ctxt->attr[i].attr->name,
3924 node->name);
3925 }
3926 }
3927 return(ret);
3928}
3929
3930/**
3931 * xmlSchemaValidateSimpleContent:
3932 * @ctxt: a schema validation context
3933 * @elem: an element
3934 * @type: the type declaration
3935 *
3936 * Validate the content of an element expected to be a simple type
3937 *
3938 * Returns 0 if the element is schemas valid, a positive error code
3939 * number otherwise and -1 in case of internal or API error.
3940 */
3941static int
3942xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
3943 ATTRIBUTE_UNUSED xmlNodePtr node) {
3944 xmlNodePtr child;
3945 xmlSchemaTypePtr type, base;
3946 xmlChar *value;
3947 int ret = 0, tmp;
3948
3949 child = ctxt->node;
3950 type = ctxt->type;
3951
3952 /*
3953 * Validation Rule: Element Locally Valid (Type): 3.1.3
3954 */
3955 value = xmlNodeGetContent(child);
3956 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
3957 switch (type->type) {
3958 case XML_SCHEMA_TYPE_RESTRICTION: {
3959 xmlSchemaFacetPtr facet;
3960
3961 base = type->baseType;
3962 if (base != NULL) {
3963 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
3964 } else {
3965 TODO
3966 }
3967 if (ret == 0) {
3968 facet = type->facets;
3969 while (facet != NULL) {
3970 tmp = xmlSchemaValidateFacet(base, facet, value,
3971 ctxt->value);
3972 if (tmp != 0)
3973 ret = tmp;
3974 facet = facet->next;
3975 }
3976 }
3977 break;
3978 }
3979 default:
3980 TODO
3981 }
3982 if (value != NULL)
3983 xmlFree(value);
3984
3985 return(ret);
3986}
3987
3988/**
3989 * xmlSchemaValidateCheckNodeList
3990 * @nodelist: the list of nodes
3991 *
3992 * Check the node list is only made of text nodes and entities pointing
3993 * to text nodes
3994 *
3995 * Returns 1 if true, 0 if false and -1 in case of error
3996 */
3997static int
3998xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist) {
3999 while (nodelist != NULL) {
4000 if (nodelist->type == XML_ENTITY_REF_NODE) {
4001 TODO /* implement recursion in the entity content */
4002 }
4003 if ((nodelist->type != XML_TEXT_NODE) &&
4004 (nodelist->type != XML_COMMENT_NODE) &&
4005 (nodelist->type != XML_PI_NODE) &&
4006 (nodelist->type != XML_PI_NODE)) {
4007 return(0);
4008 }
4009 nodelist = nodelist->next;
4010 }
4011 return(1);
4012}
4013
4014/**
4015 * xmlSchemaSkipIgnored:
4016 * @ctxt: a schema validation context
4017 * @type: the current type context
4018 * @node: the top node.
4019 *
4020 * Skip ignorable nodes in that context
4021 *
4022 * Returns the new sibling
4023 * number otherwise and -1 in case of internal or API error.
4024 */
4025static xmlNodePtr
4026xmlSchemaSkipIgnored(ATTRIBUTE_UNUSED xmlSchemaValidCtxtPtr ctxt,
4027 xmlSchemaTypePtr type,
4028 xmlNodePtr node) {
4029 int mixed = 0;
4030 /*
4031 * TODO complete and handle entities
4032 */
4033 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
4034 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
4035 while ((node != NULL) &&
4036 ((node->type == XML_COMMENT_NODE) ||
4037 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
4038 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
4039 (node->type == XML_TEXT_NODE) &&
4040 (IS_BLANK_NODE(node)))))) {
4041 node = node->next;
4042 }
4043 return(node);
4044}
4045
4046/**
4047 * xmlSchemaValidateCallback:
4048 * @ctxt: a schema validation context
4049 * @name: the name of the element detected (might be NULL)
4050 * @type: the type
4051 *
4052 * A transition has been made in the automata associated to an element
4053 * content model
4054 */
4055static void
4056xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
4057 ATTRIBUTE_UNUSED const xmlChar *name,
4058 xmlSchemaTypePtr type,
4059 xmlNodePtr node) {
4060 xmlSchemaTypePtr oldtype = ctxt->type;
4061 xmlNodePtr oldnode = ctxt->node;
4062#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00004063 xmlGenericError(xmlGenericErrorContext,
4064 "xmlSchemaValidateCallback: %s, %s, %s\n",
4065 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004066#endif
4067 ctxt->type = type;
4068 ctxt->node = node;
4069 xmlSchemaValidateContent(ctxt, node);
4070 ctxt->type = oldtype;
4071 ctxt->node = oldnode;
4072}
4073
4074
4075#if 0
4076/**
4077 * xmlSchemaValidateSimpleRestrictionType:
4078 * @ctxt: a schema validation context
4079 * @node: the top node.
4080 *
4081 * Validate the content of a restriction type.
4082 *
4083 * Returns 0 if the element is schemas valid, a positive error code
4084 * number otherwise and -1 in case of internal or API error.
4085 */
4086static int
4087xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
4088 xmlNodePtr node)
4089{
4090 xmlNodePtr child;
4091 xmlSchemaTypePtr type;
4092 int ret;
4093
4094 child = ctxt->node;
4095 type = ctxt->type;
4096
4097 if ((ctxt == NULL) || (type == NULL)) {
4098 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4099 if (ctxt->error != NULL)
4100 ctxt->error(ctxt->userData,
4101 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
4102 node->name);
4103 return (-1);
4104 }
4105 /*
4106 * Only text and text based entities references shall be found there
4107 */
4108 ret = xmlSchemaValidateCheckNodeList(child);
4109 if (ret < 0) {
4110 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4111 if (ctxt->error != NULL)
4112 ctxt->error(ctxt->userData,
4113 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4114 node->name);
4115 return (-1);
4116 } else if (ret == 0) {
4117 ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4118 if (ctxt->error != NULL)
4119 ctxt->error(ctxt->userData,
4120 "Element %s content is not a simple type\n",
4121 node->name);
4122 return (-1);
4123 }
4124 ctxt->type = type->subtypes;
4125 xmlSchemaValidateContent(ctxt, node);
4126 ctxt->type = type;
4127 return (ret);
4128}
4129#endif
4130
4131/**
4132 * xmlSchemaValidateSimpleType:
4133 * @ctxt: a schema validation context
4134 * @node: the top node.
4135 *
4136 * Validate the content of an simple type.
4137 *
4138 * Returns 0 if the element is schemas valid, a positive error code
4139 * number otherwise and -1 in case of internal or API error.
4140 */
4141static int
4142xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4143 xmlNodePtr child;
4144 xmlSchemaTypePtr type;
4145 xmlAttrPtr attr;
4146 int ret;
4147
4148 child = ctxt->node;
4149 type = ctxt->type;
4150
4151 if ((ctxt == NULL) || (type == NULL)) {
4152 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4153 if (ctxt->error != NULL)
4154 ctxt->error(ctxt->userData,
4155 "Internal error: xmlSchemaValidateSimpleType %s\n",
4156 node->name);
4157 return(-1);
4158 }
4159 /*
4160 * Only text and text based entities references shall be found there
4161 */
4162 ret = xmlSchemaValidateCheckNodeList(child);
4163 if (ret < 0) {
4164 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4165 if (ctxt->error != NULL)
4166 ctxt->error(ctxt->userData,
4167 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4168 node->name);
4169 return(-1);
4170 } else if (ret == 0) {
4171 ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4172 if (ctxt->error != NULL)
4173 ctxt->error(ctxt->userData,
4174 "Element %s content is not a simple type\n",
4175 node->name);
4176 return(-1);
4177 }
4178 /*
4179 * Validation Rule: Element Locally Valid (Type): 3.1.1
4180 */
4181 attr = node->properties;
4182 while (attr != NULL) {
4183 if ((attr->ns == NULL) ||
4184 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
4185 ((!xmlStrEqual(attr->name, BAD_CAST"type")) &&
4186 (!xmlStrEqual(attr->name, BAD_CAST"nil")) &&
4187 (!xmlStrEqual(attr->name, BAD_CAST"schemasLocation")) &&
4188 (!xmlStrEqual(attr->name, BAD_CAST"noNamespaceSchemaLocation")))) {
4189 ctxt->err = XML_SCHEMAS_ERR_INVALIDATTR;
4190 if (ctxt->error != NULL)
4191 ctxt->error(ctxt->userData,
4192 "Element %s: attribute %s should not be present\n",
4193 child->name, attr->name);
4194 return(ctxt->err);
4195 }
4196 }
4197
4198 ctxt->type = type->subtypes;
4199 ret = xmlSchemaValidateSimpleContent(ctxt, node);
4200 ctxt->type = type;
4201 return(ret);
4202}
4203
4204/**
4205 * xmlSchemaValidateElementType:
4206 * @ctxt: a schema validation context
4207 * @node: the top node.
4208 *
4209 * Validate the content of an element type.
4210 * Validation Rule: Element Locally Valid (Complex Type)
4211 *
4212 * Returns 0 if the element is schemas valid, a positive error code
4213 * number otherwise and -1 in case of internal or API error.
4214 */
4215static int
4216xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4217 xmlNodePtr child;
4218 xmlSchemaTypePtr type;
4219 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
4220 xmlSchemaElementPtr decl;
4221 int ret, attrBase;
4222
4223 oldregexp = ctxt->regexp;
4224
4225 child = ctxt->node;
4226 type = ctxt->type;
4227
4228 if ((ctxt == NULL) || (type == NULL)) {
4229 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4230 if (ctxt->error != NULL)
4231 ctxt->error(ctxt->userData,
4232 "Internal error: xmlSchemaValidateElementType\n",
4233 node->name);
4234 return(-1);
4235 }
4236 if (child == NULL) {
4237 if (type->minOccurs > 0) {
4238 ctxt->err = XML_SCHEMAS_ERR_MISSING;
4239 if (ctxt->error != NULL)
4240 ctxt->error(ctxt->userData,
4241 "Element %s: missing child %s\n",
4242 node->name, type->name);
4243 }
4244 return(ctxt->err);
4245 }
4246
4247 /*
4248 * Verify the element matches
4249 */
4250 if (!xmlStrEqual(child->name, type->name)) {
4251 ctxt->err = XML_SCHEMAS_ERR_WRONGELEM;
4252 if (ctxt->error != NULL)
4253 ctxt->error(ctxt->userData,
4254 "Element %s: missing child %s found %s\n",
4255 node->name, type->name, child->name);
4256 return(ctxt->err);
4257 }
4258 /*
4259 * Verify the attributes
4260 */
4261 attrBase = ctxt->attrBase;
4262 ctxt->attrBase = ctxt->attrNr;
4263 xmlSchemaRegisterAttributes(ctxt, child->properties);
4264 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
4265 /*
4266 * Verify the element content recursively
4267 */
4268 decl = (xmlSchemaElementPtr) type;
4269 oldregexp = ctxt->regexp;
4270 if (decl->contModel != NULL) {
4271 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
4272 (xmlRegExecCallbacks) xmlSchemaValidateCallback,
4273 ctxt);
4274#ifdef DEBUG_AUTOMATA
4275 xmlGenericError(xmlGenericErrorContext,
4276 "====> %s\n", node->name);
4277#endif
4278 }
4279 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr)type,
4280 type->subtypes);
4281
4282 if (decl->contModel != NULL) {
4283 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
4284#ifdef DEBUG_AUTOMATA
4285 xmlGenericError(xmlGenericErrorContext,
4286 "====> %s : %d\n", node->name, ret);
4287#endif
4288 if (ret == 0) {
Daniel Veillard8651f532002-04-17 09:06:27 +00004289 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
Daniel Veillard4255d502002-04-16 15:50:10 +00004290 if (ctxt->error != NULL)
4291 ctxt->error(ctxt->userData, "Element %s content check failed\n",
4292 node->name);
4293 } else if (ret < 0) {
Daniel Veillard8651f532002-04-17 09:06:27 +00004294 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
Daniel Veillard4255d502002-04-16 15:50:10 +00004295 if (ctxt->error != NULL)
4296 ctxt->error(ctxt->userData, "Element %s content check failure\n",
4297 node->name);
4298#ifdef DEBUG_CONTENT
4299 } else {
4300 xmlGenericError(xmlGenericErrorContext,
4301 "Element %s content check succeeded\n", node->name);
4302
4303#endif
4304 }
4305 xmlRegFreeExecCtxt(ctxt->regexp);
4306 }
4307 /*
4308 * Verify that all attributes were Schemas-validated
4309 */
4310 xmlSchemaCheckAttributes(ctxt, node);
4311 ctxt->attrNr = ctxt->attrBase;
4312 ctxt->attrBase = attrBase;
4313
4314 ctxt->regexp = oldregexp;
4315
4316 ctxt->node = child;
4317 ctxt->type = type;
4318 return(ctxt->err);
4319}
4320
4321/**
4322 * xmlSchemaValidateBasicType:
4323 * @ctxt: a schema validation context
4324 * @node: the top node.
4325 *
4326 * Validate the content of an element expected to be a basic type type
4327 *
4328 * Returns 0 if the element is schemas valid, a positive error code
4329 * number otherwise and -1 in case of internal or API error.
4330 */
4331static int
4332xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4333 int ret;
4334 xmlNodePtr child, cur;
4335 xmlSchemaTypePtr type;
4336 xmlChar *value; /* lexical representation */
4337
4338 child = ctxt->node;
4339 type = ctxt->type;
4340
4341 if ((ctxt == NULL) || (type == NULL)) {
4342 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4343 if (ctxt->error != NULL)
4344 ctxt->error(ctxt->userData,
4345 "Internal error: xmlSchemaValidateBasicType\n",
4346 node->name);
4347 return(-1);
4348 }
4349 /*
4350 * First check the content model of the node.
4351 */
4352 cur = child;
4353 while (cur != NULL) {
4354 switch (cur->type) {
4355 case XML_TEXT_NODE:
4356 case XML_CDATA_SECTION_NODE:
4357 case XML_PI_NODE:
4358 case XML_COMMENT_NODE:
4359 case XML_XINCLUDE_START:
4360 case XML_XINCLUDE_END:
4361 break;
4362 case XML_ENTITY_REF_NODE:
4363 case XML_ENTITY_NODE:
4364 TODO
4365 break;
4366 case XML_ELEMENT_NODE:
4367 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
4368 if (ctxt->error != NULL)
4369 ctxt->error(ctxt->userData,
4370 "Element %s: child %s should not be present\n",
4371 node->name, cur->name);
4372 return(ctxt->err);
4373 case XML_ATTRIBUTE_NODE:
4374 case XML_DOCUMENT_NODE:
4375 case XML_DOCUMENT_TYPE_NODE:
4376 case XML_DOCUMENT_FRAG_NODE:
4377 case XML_NOTATION_NODE:
4378 case XML_HTML_DOCUMENT_NODE:
4379 case XML_DTD_NODE:
4380 case XML_ELEMENT_DECL:
4381 case XML_ATTRIBUTE_DECL:
4382 case XML_ENTITY_DECL:
4383 case XML_NAMESPACE_DECL:
4384#ifdef LIBXML_DOCB_ENABLED
4385 case XML_DOCB_DOCUMENT_NODE:
4386#endif
4387 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
4388 if (ctxt->error != NULL)
4389 ctxt->error(ctxt->userData,
4390 "Element %s: node type %d unexpected here\n",
4391 node->name, cur->type);
4392 return(ctxt->err);
4393 }
4394 cur = cur->next;
4395 }
4396 if (child == NULL)
4397 value = NULL;
4398 else
4399 value = xmlNodeGetContent(child->parent);
4400
4401 if (ctxt->value != NULL) {
4402 xmlSchemaFreeValue(ctxt->value);
4403 ctxt->value = NULL;
4404 }
4405 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
4406 if (value != NULL)
4407 xmlFree(value);
4408 if (ret != 0) {
4409 ctxt->error(ctxt->userData,
4410 "Element %s: failed to validate basic type %s\n",
4411 node->name, type->name);
4412 }
4413 return(ret);
4414}
4415
4416/**
4417 * xmlSchemaValidateComplexType:
4418 * @ctxt: a schema validation context
4419 * @node: the top node.
4420 *
4421 * Validate the content of an element expected to be a complex type type
4422 * xmlschema-1.html#cvc-complex-type
4423 * Validation Rule: Element Locally Valid (Complex Type)
4424 *
4425 * Returns 0 if the element is schemas valid, a positive error code
4426 * number otherwise and -1 in case of internal or API error.
4427 */
4428static int
4429xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4430 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00004431 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004432 int ret;
4433
4434 child = ctxt->node;
4435 type = ctxt->type;
4436
4437 /* 3.4.4 1 was verified on the caller */
4438
4439 switch (type->contentType) {
4440 case XML_SCHEMA_CONTENT_EMPTY:
4441 if (child != NULL) {
4442 if (ctxt->error != NULL)
4443 ctxt->error(ctxt->userData,
4444 "Element %s is supposed to be empty\n",
4445 node->name);
4446 }
4447 break;
4448 case XML_SCHEMA_CONTENT_ELEMENTS:
4449 case XML_SCHEMA_CONTENT_MIXED:
4450 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4451 /*
4452 * Skip ignorable nodes in that context
4453 */
4454 child = xmlSchemaSkipIgnored(ctxt, type, child);
4455 subtype = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004456 while (child != NULL) {
4457 if (child->type == XML_ELEMENT_NODE) {
4458 ret = xmlRegExecPushString(ctxt->regexp,
4459 child->name, child);
4460#ifdef DEBUG_AUTOMATA
4461 if (ret < 0)
4462 xmlGenericError(xmlGenericErrorContext,
4463 " --> %s Error\n", child->name);
4464 else
4465 xmlGenericError(xmlGenericErrorContext,
4466 " --> %s\n", child->name);
4467#endif
4468 }
4469 child = child->next;
4470 /*
4471 * Skip ignorable nodes in that context
4472 */
4473 child = xmlSchemaSkipIgnored(ctxt, type, child);
4474 }
4475 break;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004476 case XML_SCHEMA_CONTENT_BASIC: {
4477 if (type->subtypes != NULL) {
4478 ctxt->type = type->subtypes;
4479 xmlSchemaValidateComplexType(ctxt, node);
4480 }
4481 if (type->baseType != NULL) {
4482 ctxt->type = type->baseType;
4483 xmlSchemaValidateBasicType(ctxt, node);
4484 }
4485 if (type->attributes != NULL) {
4486 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4487 }
4488 ctxt->type = type;
4489 break;
4490 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004491 default:
4492 TODO
4493 xmlGenericError(xmlGenericErrorContext,
4494 "unimplemented content type %d\n",
4495 type->contentType);
4496 }
4497 return(ctxt->err);
4498}
4499
4500/**
4501 * xmlSchemaValidateContent:
4502 * @ctxt: a schema validation context
4503 * @elem: an element
4504 * @type: the type declaration
4505 *
4506 * Validate the content of an element against the type.
4507 *
4508 * Returns 0 if the element is schemas valid, a positive error code
4509 * number otherwise and -1 in case of internal or API error.
4510 */
4511static int
4512xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4513 xmlNodePtr child;
4514 xmlSchemaTypePtr type;
4515
4516 child = ctxt->node;
4517 type = ctxt->type;
4518
4519 switch (type->type) {
4520 case XML_SCHEMA_TYPE_ANY:
4521 /* Any type will do it, fine */
4522 TODO /* handle recursivity */
4523 break;
4524 case XML_SCHEMA_TYPE_COMPLEX:
4525 xmlSchemaValidateComplexType(ctxt, node);
4526 break;
4527 case XML_SCHEMA_TYPE_ELEMENT: {
4528 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
4529 /*
4530 * Handle element reference here
4531 */
4532 if (decl->ref != NULL) {
4533 if (decl->refDecl == NULL) {
4534 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4535 if (ctxt->error != NULL)
4536 ctxt->error(ctxt->userData,
4537 "Internal error: element reference %s not resolved\n",
4538 decl->ref);
4539 return(-1);
4540 }
4541 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
4542 decl = decl->refDecl;
4543 }
4544 xmlSchemaValidateElementType(ctxt, node);
4545 ctxt->type = type;
4546 break;
4547 }
4548 case XML_SCHEMA_TYPE_BASIC:
4549 xmlSchemaValidateBasicType(ctxt, node);
4550 break;
4551 case XML_SCHEMA_TYPE_FACET:
4552 TODO
4553 break;
4554 case XML_SCHEMA_TYPE_SIMPLE:
4555 xmlSchemaValidateSimpleType(ctxt, node);
4556 break;
4557 case XML_SCHEMA_TYPE_SEQUENCE:
4558 TODO
4559 break;
4560 case XML_SCHEMA_TYPE_CHOICE:
4561 TODO
4562 break;
4563 case XML_SCHEMA_TYPE_ALL:
4564 TODO
4565 break;
4566 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
4567 TODO
4568 break;
4569 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4570 TODO
4571 break;
4572 case XML_SCHEMA_TYPE_UR:
4573 TODO
4574 break;
4575 case XML_SCHEMA_TYPE_RESTRICTION:
4576 /*xmlSchemaValidateRestrictionType(ctxt, node); */
4577 TODO
4578 break;
4579 case XML_SCHEMA_TYPE_EXTENSION:
4580 TODO
4581 break;
4582 case XML_SCHEMA_TYPE_ATTRIBUTE:
4583 TODO
4584 break;
4585 case XML_SCHEMA_TYPE_GROUP:
4586 TODO
4587 break;
4588 case XML_SCHEMA_TYPE_NOTATION:
4589 TODO
4590 break;
4591 case XML_SCHEMA_TYPE_LIST:
4592 TODO
4593 break;
4594 case XML_SCHEMA_TYPE_UNION:
4595 TODO
4596 break;
4597 case XML_SCHEMA_FACET_MININCLUSIVE:
4598 TODO
4599 break;
4600 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4601 TODO
4602 break;
4603 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4604 TODO
4605 break;
4606 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4607 TODO
4608 break;
4609 case XML_SCHEMA_FACET_TOTALDIGITS:
4610 TODO
4611 break;
4612 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4613 TODO
4614 break;
4615 case XML_SCHEMA_FACET_PATTERN:
4616 TODO
4617 break;
4618 case XML_SCHEMA_FACET_ENUMERATION:
4619 TODO
4620 break;
4621 case XML_SCHEMA_FACET_WHITESPACE:
4622 TODO
4623 break;
4624 case XML_SCHEMA_FACET_LENGTH:
4625 TODO
4626 break;
4627 case XML_SCHEMA_FACET_MAXLENGTH:
4628 TODO
4629 break;
4630 case XML_SCHEMA_FACET_MINLENGTH:
4631 TODO
4632 break;
4633 }
4634 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4635
4636 if (ctxt->node == NULL)
4637 return(ctxt->err);
4638 ctxt->node = ctxt->node->next;
4639 ctxt->type = type->next;
4640 return(ctxt->err);
4641}
4642
4643/**
4644 * xmlSchemaValidateType:
4645 * @ctxt: a schema validation context
4646 * @elem: an element
4647 * @type: the list of type declarations
4648 *
4649 * Validate the content of an element against the types.
4650 *
4651 * Returns 0 if the element is schemas valid, a positive error code
4652 * number otherwise and -1 in case of internal or API error.
4653 */
4654static int
4655xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
4656 xmlSchemaElementPtr elemDecl,
4657 xmlSchemaTypePtr type) {
4658 xmlChar *nil;
4659
4660 if ((elem->content == NULL) || (type == NULL) || (elemDecl == NULL))
4661 return(0);
4662 /*
4663 * 3.3.4 : 2
4664 */
4665 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
4666 ctxt->err = XML_SCHEMAS_ERR_ISABSTRACT;
4667 if (ctxt->error != NULL)
4668 ctxt->error(ctxt->userData, "Element %s is abstract\n", elem->name);
4669 return(ctxt->err);
4670 }
4671 /*
4672 * 3.3.4: 3
4673 */
4674 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
4675 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
4676 /* 3.3.4: 3.2 */
4677 if (xmlStrEqual(nil, BAD_CAST "true")) {
4678 if (elem->children != NULL) {
4679 ctxt->err = XML_SCHEMAS_ERR_NOTEMPTY;
4680 if (ctxt->error != NULL)
4681 ctxt->error(ctxt->userData, "Element %s is not empty\n",
4682 elem->name);
4683 return(ctxt->err);
4684 }
4685 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
4686 (elemDecl->value != NULL)) {
4687 ctxt->err = XML_SCHEMAS_ERR_HAVEDEFAULT;
4688 if (ctxt->error != NULL)
4689 ctxt->error(ctxt->userData,
4690 "Empty element %s cannot get a fixed value\n",
4691 elem->name);
4692 return(ctxt->err);
4693 }
4694 }
4695 } else {
4696 /* 3.3.4: 3.1 */
4697 if (nil != NULL) {
4698 ctxt->err = XML_SCHEMAS_ERR_NOTNILLABLE;
4699 if (ctxt->error != NULL)
4700 ctxt->error(ctxt->userData,
4701 "Element %s with xs:nil but not nillable\n",
4702 elem->name);
4703 xmlFree(nil);
4704 return(ctxt->err);
4705 }
4706 }
4707
4708 /* TODO 3.3.4: 4 if the element carries xs:type*/
4709
4710 ctxt->type = elemDecl->subtypes;
4711 ctxt->node = elem->children;
4712 xmlSchemaValidateContent(ctxt, elem);
4713 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
4714
4715 return(ctxt->err);
4716}
4717
4718
4719/**
4720 * xmlSchemaValidateAttributes:
4721 * @ctxt: a schema validation context
4722 * @elem: an element
4723 * @attributes: the list of attribute declarations
4724 *
4725 * Validate the attributes of an element.
4726 *
4727 * Returns 0 if the element is schemas valid, a positive error code
4728 * number otherwise and -1 in case of internal or API error.
4729 */
4730static int
4731xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
4732 xmlSchemaAttributePtr attributes) {
4733 int i, ret;
4734 xmlAttrPtr attr;
4735 xmlChar *value;
4736
4737 if (attributes == NULL)
4738 return(0);
4739 while (attributes != NULL) {
4740 for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
4741 attr = ctxt->attr[i].attr;
4742 if (attr == NULL)
4743 continue;
4744 if (!xmlStrEqual(attr->name, attributes->name))
4745 continue;
4746 /*
4747 * TODO: handle the mess about namespaces here.
4748 */
4749 if ((attr->ns != NULL) /* || (attributes->ns != NULL) */) {
4750 TODO
4751 }
4752 if (attributes->subtypes == NULL) {
4753 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4754 if (ctxt->error != NULL)
4755 ctxt->error(ctxt->userData,
4756 "Internal error: attribute %s type not resolved\n",
4757 attr->name);
4758 continue;
4759 }
4760 value = xmlNodeListGetString(elem->doc, attr->children, 1);
4761 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
4762 value);
4763 if (ret != 0) {
4764 ctxt->err = XML_SCHEMAS_ERR_ATTRINVALID;
4765 if (ctxt->error != NULL)
4766 ctxt->error(ctxt->userData,
4767 "attribute %s on %s does not match type\n",
4768 attr->name, elem->name);
4769 } else {
4770 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
4771 }
4772 if (value != NULL) {
4773 xmlFree(value);
4774 }
4775 }
4776 attributes = attributes->next;
4777 }
4778 return(ctxt->err);
4779}
4780
4781/**
4782 * xmlSchemaValidateElement:
4783 * @ctxt: a schema validation context
4784 * @elem: an element
4785 *
4786 * Validate an element in a tree
4787 *
4788 * Returns 0 if the element is schemas valid, a positive error code
4789 * number otherwise and -1 in case of internal or API error.
4790 */
4791static int
4792xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem) {
4793 xmlSchemaElementPtr elemDecl;
4794 int ret, attrBase;
4795
4796 if (elem->ns != NULL)
4797 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
4798 elem->name, elem->ns->href, NULL);
4799 else
4800 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
4801 elem->name, NULL, NULL);
4802 /*
4803 * 3.3.4 : 1
4804 */
4805 if (elemDecl == NULL) {
4806 ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
4807 if (ctxt->error != NULL)
4808 ctxt->error(ctxt->userData, "Element %s not declared\n",
4809 elem->name);
4810 return(ctxt->err);
4811 }
4812 if (elemDecl->subtypes == NULL) {
4813 ctxt->err = XML_SCHEMAS_ERR_NOTYPE;
4814 if (ctxt->error != NULL)
4815 ctxt->error(ctxt->userData, "Element %s has no type\n",
4816 elem->name);
4817 return(ctxt->err);
4818 }
4819 /*
4820 * Verify the attributes
4821 */
4822 attrBase = ctxt->attrBase;
4823 ctxt->attrBase = ctxt->attrNr;
4824 xmlSchemaRegisterAttributes(ctxt, elem->properties);
4825 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
4826 /*
4827 * Verify the element content recursively
4828 */
4829 if (elemDecl->contModel != NULL) {
4830 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
4831 (xmlRegExecCallbacks) xmlSchemaValidateCallback,
4832 ctxt);
4833#ifdef DEBUG_AUTOMATA
4834 xmlGenericError(xmlGenericErrorContext,
4835 "====> %s\n", elem->name);
4836#endif
4837 }
4838 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004839 if (elemDecl->contModel != NULL) {
4840 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004841#ifdef DEBUG_AUTOMATA
Daniel Veillard4255d502002-04-16 15:50:10 +00004842 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004843 "====> %s : %d\n", elem->name, ret);
4844#endif
4845 if (ret == 0) {
4846 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
4847 if (ctxt->error != NULL)
4848 ctxt->error(ctxt->userData, "Element %s content check failed\n",
4849 elem->name);
4850 } else if (ret < 0) {
4851 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
4852 if (ctxt->error != NULL)
4853 ctxt->error(ctxt->userData, "Element %s content check failed\n",
4854 elem->name);
4855#ifdef DEBUG_CONTENT
4856 } else {
4857 xmlGenericError(xmlGenericErrorContext,
4858 "Element %s content check succeeded\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004859
4860#endif
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004861 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004862 xmlRegFreeExecCtxt(ctxt->regexp);
4863 }
4864 /*
4865 * Verify that all attributes were Schemas-validated
4866 */
4867 xmlSchemaCheckAttributes(ctxt, elem);
4868 ctxt->attrNr = ctxt->attrBase;
4869 ctxt->attrBase = attrBase;
4870
4871 return(ctxt->err);
4872}
4873
4874/**
4875 * xmlSchemaValidateDocument:
4876 * @ctxt: a schema validation context
4877 * @doc: a parsed document tree
4878 *
4879 * Validate a document tree in memory.
4880 *
4881 * Returns 0 if the document is schemas valid, a positive error code
4882 * number otherwise and -1 in case of internal or API error.
4883 */
4884static int
4885xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
4886 xmlNodePtr root;
4887 xmlSchemaElementPtr elemDecl;
4888
4889 root = xmlDocGetRootElement(doc);
4890 if (root == NULL) {
4891 ctxt->err = XML_SCHEMAS_ERR_NOROOT;
4892 if (ctxt->error != NULL)
4893 ctxt->error(ctxt->userData, "document has no root\n");
4894 return(ctxt->err);
4895 }
4896 if (root->ns != NULL)
4897 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
4898 root->name, root->ns->href, NULL);
4899 else
4900 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
4901 root->name, NULL, NULL);
4902 if (elemDecl == NULL) {
4903 ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
4904 if (ctxt->error != NULL)
4905 ctxt->error(ctxt->userData, "Element %s not declared\n",
4906 root->name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004907 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004908 ctxt->err = XML_SCHEMAS_ERR_NOTTOPLEVEL;
4909 if (ctxt->error != NULL)
4910 ctxt->error(ctxt->userData, "Root element %s not toplevel\n",
4911 root->name);
4912 }
4913 /*
4914 * Okay, start the recursive validation
4915 */
4916 xmlSchemaValidateElement(ctxt, root);
4917
4918 return(ctxt->err);
4919}
4920
4921/************************************************************************
4922 * *
4923 * SAX Validation code *
4924 * *
4925 ************************************************************************/
4926
4927/************************************************************************
4928 * *
4929 * Validation interfaces *
4930 * *
4931 ************************************************************************/
4932
4933/**
4934 * xmlSchemaNewValidCtxt:
4935 * @schema: a precompiled XML Schemas
4936 *
4937 * Create an XML Schemas validation context based on the given schema
4938 *
4939 * Returns the validation context or NULL in case of error
4940 */
4941xmlSchemaValidCtxtPtr
4942xmlSchemaNewValidCtxt(xmlSchemaPtr schema) {
4943 xmlSchemaValidCtxtPtr ret;
4944
4945 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
4946 if (ret == NULL) {
4947 xmlGenericError(xmlGenericErrorContext,
4948 "Failed to allocate new schama validation context\n");
4949 return (NULL);
4950 }
4951 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
4952 ret->schema = schema;
4953 ret->attrNr = 0;
4954 ret->attrMax = 10;
4955 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
4956 sizeof(xmlSchemaAttrState));
4957 if (ret->attr == NULL) {
4958 free(ret);
4959 return(NULL);
4960 }
4961 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
4962 return (ret);
4963}
4964
4965/**
4966 * xmlSchemaFreeValidCtxt:
4967 * @ctxt: the schema validation context
4968 *
4969 * Free the resources associated to the schema validation context
4970 */
4971void
4972xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) {
4973 if (ctxt == NULL)
4974 return;
4975 if (ctxt->attr != NULL)
4976 xmlFree(ctxt->attr);
4977 xmlFree(ctxt);
4978}
4979
4980/**
4981 * xmlSchemaSetValidErrors:
4982 * @ctxt: a schema validation context
4983 * @err: the error function
4984 * @warn: the warning function
4985 * @ctxt: the functions context
4986 *
4987 * Set the error and warning callback informations
4988 */
4989void
4990xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
4991 xmlSchemaValidityErrorFunc err,
4992 xmlSchemaValidityWarningFunc warn, void *ctx) {
4993 if (ctxt == NULL)
4994 return;
4995 ctxt->error = err;
4996 ctxt->warning = warn;
4997 ctxt->userData = ctx;
4998}
4999
5000/**
5001 * xmlSchemaValidateDoc:
5002 * @ctxt: a schema validation context
5003 * @doc: a parsed document tree
5004 *
5005 * Validate a document tree in memory.
5006 *
5007 * Returns 0 if the document is schemas valid, a positive error code
5008 * number otherwise and -1 in case of internal or API error.
5009 */
5010int
5011xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5012 int ret;
5013
5014 if ((ctxt == NULL) || (doc == NULL))
5015 return(-1);
5016
5017 ctxt->doc = doc;
5018 ret = xmlSchemaValidateDocument(ctxt, doc);
5019 return(ret);
5020}
5021
5022/**
5023 * xmlSchemaValidateStream:
5024 * @ctxt: a schema validation context
5025 * @input: the input to use for reading the data
5026 * @enc: an optional encoding information
5027 * @sax: a SAX handler for the resulting events
5028 * @user_data: the context to provide to the SAX handler.
5029 *
5030 * Validate a document tree in memory.
5031 *
5032 * Returns 0 if the document is schemas valid, a positive error code
5033 * number otherwise and -1 in case of internal or API error.
5034 */
5035int
5036xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
5037 xmlParserInputBufferPtr input, xmlCharEncoding enc,
5038 xmlSAXHandlerPtr sax, void *user_data) {
5039 if ((ctxt == NULL) || (input == NULL))
5040 return(-1);
5041 ctxt->input = input;
5042 ctxt->enc = enc;
5043 ctxt->sax = sax;
5044 ctxt->user_data = user_data;
5045 TODO
5046 return(0);
5047}
5048
5049#endif /* LIBXML_SCHEMAS_ENABLED */