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