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