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