blob: 15ff701fbbf587206586dffad2c2e85e7cc3f0a6 [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 }
2271 TODO
2272
2273 child = node->children;
2274 while (IS_SCHEMA(child, "annotation")) {
2275 child = child->next;
2276 }
2277 if (child != NULL) {
2278 xmlSchemaErrorContext(ctxt, schema, node, child);
2279 if ((ctxt != NULL) && (ctxt->error != NULL))
2280 ctxt->error(ctxt->userData,
2281 "Import has unexpected content\n");
2282 return(-1);
2283 }
2284 return(1);
2285}
2286
2287/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002288 * xmlSchemaParseChoice:
2289 * @ctxt: a schema validation context
2290 * @schema: the schema being built
2291 * @node: a subtree containing XML Schema informations
2292 *
2293 * parse a XML schema Choice definition
2294 * *WARNING* this interface is highly subject to change
2295 *
2296 * Returns -1 in case of error, 0 if the declaration is inproper and
2297 * 1 in case of success.
2298 */
2299static xmlSchemaTypePtr
2300xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2301 xmlNodePtr node)
2302{
2303 xmlSchemaTypePtr type, subtype, last = NULL;
2304 xmlNodePtr child = NULL;
2305 xmlChar name[30];
2306
2307 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2308 return (NULL);
2309
2310
2311 snprintf((char *)name, 30, "choice %d", ctxt->counter++ + 1);
2312 type = xmlSchemaAddType(ctxt, schema, name);
2313 if (type == NULL)
2314 return (NULL);
2315 type->node = node;
2316 type->type = XML_SCHEMA_TYPE_CHOICE;
2317 type->id = xmlGetProp(node, BAD_CAST "id");
2318 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2319 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2320
2321 child = node->children;
2322 if (IS_SCHEMA(child, "annotation")) {
2323 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2324 child = child->next;
2325 }
2326 while ((IS_SCHEMA(child, "element")) ||
2327 (IS_SCHEMA(child, "group")) ||
2328 (IS_SCHEMA(child, "any")) ||
2329 (IS_SCHEMA(child, "choice")) ||
2330 (IS_SCHEMA(child, "sequence"))) {
2331 subtype = NULL;
2332 if (IS_SCHEMA(child, "element")) {
2333 subtype = (xmlSchemaTypePtr)
2334 xmlSchemaParseElement(ctxt, schema, child, 0);
2335 } else if (IS_SCHEMA(child, "group")) {
2336 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2337 } else if (IS_SCHEMA(child, "any")) {
2338 subtype = xmlSchemaParseAny(ctxt, schema, child);
2339 } else if (IS_SCHEMA(child, "sequence")) {
2340 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2341 } else if (IS_SCHEMA(child, "choice")) {
2342 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2343 }
2344 if (subtype != NULL) {
2345 if (last == NULL) {
2346 type->subtypes = subtype;
2347 last = subtype;
2348 } else {
2349 last->next = subtype;
2350 last = subtype;
2351 }
2352 last->next = NULL;
2353 }
2354 child = child->next;
2355 }
2356 if (child != NULL) {
2357 xmlSchemaErrorContext(ctxt, schema, node, child);
2358 if ((ctxt != NULL) && (ctxt->error != NULL))
2359 ctxt->error(ctxt->userData,
2360 "Choice %s has unexpected content\n",
2361 type->name);
2362 }
2363
2364 return (type);
2365}
2366
2367/**
2368 * xmlSchemaParseSequence:
2369 * @ctxt: a schema validation context
2370 * @schema: the schema being built
2371 * @node: a subtree containing XML Schema informations
2372 *
2373 * parse a XML schema Sequence definition
2374 * *WARNING* this interface is highly subject to change
2375 *
2376 * Returns -1 in case of error, 0 if the declaration is inproper and
2377 * 1 in case of success.
2378 */
2379static xmlSchemaTypePtr
2380xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2381 xmlNodePtr node)
2382{
2383 xmlSchemaTypePtr type, subtype, last = NULL;
2384 xmlNodePtr child = NULL;
2385 xmlChar name[30];
2386
2387 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2388 return (NULL);
2389
2390
2391 snprintf((char *)name, 30, "sequence %d", ctxt->counter++ + 1);
2392 type = xmlSchemaAddType(ctxt, schema, name);
2393 if (type == NULL)
2394 return (NULL);
2395 type->node = node;
2396 type->type = XML_SCHEMA_TYPE_SEQUENCE;
2397 type->id = xmlGetProp(node, BAD_CAST "id");
2398 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2399 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2400
2401 child = node->children;
2402 if (IS_SCHEMA(child, "annotation")) {
2403 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2404 child = child->next;
2405 }
2406 while ((IS_SCHEMA(child, "element")) ||
2407 (IS_SCHEMA(child, "group")) ||
2408 (IS_SCHEMA(child, "any")) ||
2409 (IS_SCHEMA(child, "choice")) ||
2410 (IS_SCHEMA(child, "sequence"))) {
2411 subtype = NULL;
2412 if (IS_SCHEMA(child, "element")) {
2413 subtype = (xmlSchemaTypePtr)
2414 xmlSchemaParseElement(ctxt, schema, child, 0);
2415 } else if (IS_SCHEMA(child, "group")) {
2416 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2417 } else if (IS_SCHEMA(child, "any")) {
2418 subtype = xmlSchemaParseAny(ctxt, schema, child);
2419 } else if (IS_SCHEMA(child, "choice")) {
2420 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2421 } else if (IS_SCHEMA(child, "sequence")) {
2422 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2423 }
2424 if (subtype != NULL) {
2425 if (last == NULL) {
2426 type->subtypes = subtype;
2427 last = subtype;
2428 } else {
2429 last->next = subtype;
2430 last = subtype;
2431 }
2432 last->next = NULL;
2433 }
2434 child = child->next;
2435 }
2436 if (child != NULL) {
2437 xmlSchemaErrorContext(ctxt, schema, node, child);
2438 if ((ctxt != NULL) && (ctxt->error != NULL))
2439 ctxt->error(ctxt->userData,
2440 "Sequence %s has unexpected content\n",
2441 type->name);
2442 }
2443
2444 return (type);
2445}
2446
2447/**
2448 * xmlSchemaParseRestriction:
2449 * @ctxt: a schema validation context
2450 * @schema: the schema being built
2451 * @node: a subtree containing XML Schema informations
2452 * @simple: is that part of a simple type.
2453 *
2454 * parse a XML schema Restriction definition
2455 * *WARNING* this interface is highly subject to change
2456 *
2457 * Returns the type definition or NULL in case of error
2458 */
2459static xmlSchemaTypePtr
2460xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2461 xmlNodePtr node, int simple)
2462{
2463 xmlSchemaTypePtr type, subtype;
2464 xmlSchemaFacetPtr facet, lastfacet = NULL;
2465 xmlNodePtr child = NULL;
2466 xmlChar name[30];
2467 xmlChar *oldcontainer;
2468
2469 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2470 return (NULL);
2471
2472 oldcontainer = ctxt->container;
2473
2474 snprintf((char *)name, 30, "restriction %d", ctxt->counter++ + 1);
2475 type = xmlSchemaAddType(ctxt, schema, name);
2476 if (type == NULL)
2477 return (NULL);
2478 type->node = node;
2479 type->type = XML_SCHEMA_TYPE_RESTRICTION;
2480 type->id = xmlGetProp(node, BAD_CAST "id");
2481 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2482 if ((!simple) && (type->base == NULL)) {
2483 xmlSchemaErrorContext(ctxt, schema, node, child);
2484 if ((ctxt != NULL) && (ctxt->error != NULL))
2485 ctxt->error(ctxt->userData,
2486 "Restriction %s has no base\n",
2487 type->name);
2488 }
2489 ctxt->container = name;
2490
2491 child = node->children;
2492 if (IS_SCHEMA(child, "annotation")) {
2493 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2494 child = child->next;
2495 }
2496 subtype = NULL;
2497
2498 if (IS_SCHEMA(child, "all")) {
2499 subtype = (xmlSchemaTypePtr)
2500 xmlSchemaParseAll(ctxt, schema, child);
2501 child = child->next;
2502 type->subtypes = subtype;
2503 } else if (IS_SCHEMA(child, "choice")) {
2504 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2505 child = child->next;
2506 type->subtypes = subtype;
2507 } else if (IS_SCHEMA(child, "sequence")) {
2508 subtype = (xmlSchemaTypePtr)
2509 xmlSchemaParseSequence(ctxt, schema, child);
2510 child = child->next;
2511 type->subtypes = subtype;
2512 } else if (IS_SCHEMA(child, "group")) {
2513 subtype = (xmlSchemaTypePtr)
2514 xmlSchemaParseGroup(ctxt, schema, child);
2515 child = child->next;
2516 type->subtypes = subtype;
2517 } else {
2518 if (IS_SCHEMA(child, "simpleType")) {
2519 subtype = (xmlSchemaTypePtr)
2520 xmlSchemaParseSimpleType(ctxt, schema, child);
2521 child = child->next;
2522 type->baseType = subtype;
2523 }
2524 /*
2525 * Facets
2526 */
2527 while ((IS_SCHEMA(child, "minInclusive")) ||
2528 (IS_SCHEMA(child, "minExclusive")) ||
2529 (IS_SCHEMA(child, "maxInclusive")) ||
2530 (IS_SCHEMA(child, "maxExclusive")) ||
2531 (IS_SCHEMA(child, "totalDigits")) ||
2532 (IS_SCHEMA(child, "fractionDigits")) ||
2533 (IS_SCHEMA(child, "pattern")) ||
2534 (IS_SCHEMA(child, "enumeration")) ||
2535 (IS_SCHEMA(child, "whiteSpace")) ||
2536 (IS_SCHEMA(child, "length")) ||
2537 (IS_SCHEMA(child, "maxLength")) ||
2538 (IS_SCHEMA(child, "minLength"))) {
2539 facet = xmlSchemaParseFacet(ctxt, schema, child);
2540 if (facet != NULL) {
2541 if (lastfacet == NULL) {
2542 type->facets = facet;
2543 lastfacet = facet;
2544 } else {
2545 lastfacet->next = facet;
2546 lastfacet = facet;
2547 }
2548 lastfacet->next = NULL;
2549 }
2550 child = child->next;
2551 }
2552 }
2553 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2554 if (child != NULL) {
2555 xmlSchemaErrorContext(ctxt, schema, node, child);
2556 if ((ctxt != NULL) && (ctxt->error != NULL))
2557 ctxt->error(ctxt->userData,
2558 "Restriction %s has unexpected content\n",
2559 type->name);
2560 }
2561 ctxt->container = oldcontainer;
2562 return (type);
2563}
2564
2565/**
2566 * xmlSchemaParseExtension:
2567 * @ctxt: a schema validation context
2568 * @schema: the schema being built
2569 * @node: a subtree containing XML Schema informations
2570 *
2571 * parse a XML schema Extension definition
2572 * *WARNING* this interface is highly subject to change
2573 *
2574 * Returns the type definition or NULL in case of error
2575 */
2576static xmlSchemaTypePtr
2577xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2578 xmlNodePtr node)
2579{
2580 xmlSchemaTypePtr type, subtype;
2581 xmlNodePtr child = NULL;
2582 xmlChar name[30];
2583 xmlChar *oldcontainer;
2584
2585 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2586 return (NULL);
2587
2588 oldcontainer = ctxt->container;
2589
2590 snprintf((char *)name, 30, "extension %d", ctxt->counter++ + 1);
2591 type = xmlSchemaAddType(ctxt, schema, name);
2592 if (type == NULL)
2593 return (NULL);
2594 type->node = node;
2595 type->type = XML_SCHEMA_TYPE_EXTENSION;
2596 type->id = xmlGetProp(node, BAD_CAST "id");
2597 ctxt->container = name;
2598
2599 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
2600 if (type->base == NULL) {
2601 xmlSchemaErrorContext(ctxt, schema, node, child);
2602 if ((ctxt != NULL) && (ctxt->error != NULL))
2603 ctxt->error(ctxt->userData,
2604 "Extension %s has no base\n",
2605 type->name);
2606 }
2607 child = node->children;
2608 if (IS_SCHEMA(child, "annotation")) {
2609 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2610 child = child->next;
2611 }
2612 subtype = NULL;
2613
2614 if (IS_SCHEMA(child, "all")) {
2615 subtype = xmlSchemaParseAll(ctxt, schema, child);
2616 child = child->next;
2617 } else if (IS_SCHEMA(child, "choice")) {
2618 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2619 child = child->next;
2620 } else if (IS_SCHEMA(child, "sequence")) {
2621 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2622 child = child->next;
2623 } else if (IS_SCHEMA(child, "group")) {
2624 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2625 child = child->next;
2626 }
2627 if (subtype != NULL)
2628 type->subtypes = subtype;
2629 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2630 if (child != NULL) {
2631 xmlSchemaErrorContext(ctxt, schema, node, child);
2632 if ((ctxt != NULL) && (ctxt->error != NULL))
2633 ctxt->error(ctxt->userData,
2634 "Extension %s has unexpected content\n",
2635 type->name);
2636 }
2637 ctxt->container = oldcontainer;
2638 return (type);
2639}
2640
2641/**
2642 * xmlSchemaParseSimpleContent:
2643 * @ctxt: a schema validation context
2644 * @schema: the schema being built
2645 * @node: a subtree containing XML Schema informations
2646 *
2647 * parse a XML schema SimpleContent definition
2648 * *WARNING* this interface is highly subject to change
2649 *
2650 * Returns the type definition or NULL in case of error
2651 */
2652static xmlSchemaTypePtr
2653xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2654 xmlNodePtr node)
2655{
2656 xmlSchemaTypePtr type, subtype;
2657 xmlNodePtr child = NULL;
2658 xmlChar name[30];
2659
2660 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2661 return (NULL);
2662
2663
2664 snprintf((char *)name, 30, "complexContent %d", ctxt->counter++ + 1);
2665 type = xmlSchemaAddType(ctxt, schema, name);
2666 if (type == NULL)
2667 return (NULL);
2668 type->node = node;
2669 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
2670 type->id = xmlGetProp(node, BAD_CAST "id");
2671
2672 child = node->children;
2673 if (IS_SCHEMA(child, "annotation")) {
2674 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2675 child = child->next;
2676 }
2677 subtype = NULL;
2678 if (IS_SCHEMA(child, "restriction")) {
2679 subtype = (xmlSchemaTypePtr)
2680 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2681 child = child->next;
2682 } else if (IS_SCHEMA(child, "extension")) {
2683 subtype = (xmlSchemaTypePtr)
2684 xmlSchemaParseExtension(ctxt, schema, child);
2685 child = child->next;
2686 }
2687 type->subtypes = subtype;
2688 if (child != NULL) {
2689 xmlSchemaErrorContext(ctxt, schema, node, child);
2690 if ((ctxt != NULL) && (ctxt->error != NULL))
2691 ctxt->error(ctxt->userData,
2692 "SimpleContent %s has unexpected content\n",
2693 type->name);
2694 }
2695 return (type);
2696}
2697
2698/**
2699 * xmlSchemaParseComplexContent:
2700 * @ctxt: a schema validation context
2701 * @schema: the schema being built
2702 * @node: a subtree containing XML Schema informations
2703 *
2704 * parse a XML schema ComplexContent definition
2705 * *WARNING* this interface is highly subject to change
2706 *
2707 * Returns the type definition or NULL in case of error
2708 */
2709static xmlSchemaTypePtr
2710xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2711 xmlNodePtr node)
2712{
2713 xmlSchemaTypePtr type, subtype;
2714 xmlNodePtr child = NULL;
2715 xmlChar name[30];
2716
2717 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2718 return (NULL);
2719
2720
2721 snprintf((char *)name, 30, "complexContent %d", ctxt->counter++ + 1);
2722 type = xmlSchemaAddType(ctxt, schema, name);
2723 if (type == NULL)
2724 return (NULL);
2725 type->node = node;
2726 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
2727 type->id = xmlGetProp(node, BAD_CAST "id");
2728
2729 child = node->children;
2730 if (IS_SCHEMA(child, "annotation")) {
2731 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2732 child = child->next;
2733 }
2734 subtype = NULL;
2735 if (IS_SCHEMA(child, "restriction")) {
2736 subtype = (xmlSchemaTypePtr)
2737 xmlSchemaParseRestriction(ctxt, schema, child, 0);
2738 child = child->next;
2739 } else if (IS_SCHEMA(child, "extension")) {
2740 subtype = (xmlSchemaTypePtr)
2741 xmlSchemaParseExtension(ctxt, schema, child);
2742 child = child->next;
2743 }
2744 type->subtypes = subtype;
2745 if (child != NULL) {
2746 xmlSchemaErrorContext(ctxt, schema, node, child);
2747 if ((ctxt != NULL) && (ctxt->error != NULL))
2748 ctxt->error(ctxt->userData,
2749 "ComplexContent %s has unexpected content\n",
2750 type->name);
2751 }
2752 return (type);
2753}
2754
2755/**
2756 * xmlSchemaParseComplexType:
2757 * @ctxt: a schema validation context
2758 * @schema: the schema being built
2759 * @node: a subtree containing XML Schema informations
2760 *
2761 * parse a XML schema Complex Type definition
2762 * *WARNING* this interface is highly subject to change
2763 *
2764 * Returns the type definition or NULL in case of error
2765 */
2766static xmlSchemaTypePtr
2767xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2768 xmlNodePtr node)
2769{
2770 xmlSchemaTypePtr type, subtype;
2771 xmlNodePtr child = NULL;
2772 xmlChar *name;
2773 xmlChar *oldcontainer;
2774
2775 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2776 return (NULL);
2777
2778 oldcontainer = ctxt->container;
2779 name = xmlGetProp(node, (const xmlChar *) "name");
2780 if (name == NULL) {
2781 char buf[100];
2782
2783 snprintf(buf, 99, "anontype%d", ctxt->counter++ + 1);
2784 name = xmlStrdup((xmlChar *) buf);
2785 }
2786 if (name == NULL) {
2787 xmlSchemaErrorContext(ctxt, schema, node, child);
2788 if ((ctxt != NULL) && (ctxt->error != NULL))
2789 ctxt->error(ctxt->userData, "complexType has no name\n");
2790 return (NULL);
2791 }
2792 type = xmlSchemaAddType(ctxt, schema, name);
2793 if (type == NULL) {
2794 xmlFree(name);
2795 return (NULL);
2796 }
2797 type->node = node;
2798 type->type = XML_SCHEMA_TYPE_COMPLEX;
2799 type->id = xmlGetProp(node, BAD_CAST "id");
2800 ctxt->container = name;
2801
2802 child = node->children;
2803 if (IS_SCHEMA(child, "annotation")) {
2804 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2805 child = child->next;
2806 }
2807 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillarddecd64d2002-04-18 14:41:51 +00002808 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002809 child = child->next;
2810 } else if (IS_SCHEMA(child, "complexContent")) {
2811 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
2812 child = child->next;
2813 } else {
2814 subtype = NULL;
2815
2816 if (IS_SCHEMA(child, "all")) {
2817 subtype = xmlSchemaParseAll(ctxt, schema, child);
2818 child = child->next;
2819 } else if (IS_SCHEMA(child, "choice")) {
2820 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2821 child = child->next;
2822 } else if (IS_SCHEMA(child, "sequence")) {
2823 subtype = xmlSchemaParseSequence(ctxt, schema, child);
2824 child = child->next;
2825 } else if (IS_SCHEMA(child, "group")) {
2826 subtype = xmlSchemaParseGroup(ctxt, schema, child);
2827 child = child->next;
2828 }
2829 if (subtype != NULL)
2830 type->subtypes = subtype;
2831 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
2832 }
2833 if (child != NULL) {
2834 xmlSchemaErrorContext(ctxt, schema, node, child);
2835 if ((ctxt != NULL) && (ctxt->error != NULL))
2836 ctxt->error(ctxt->userData,
2837 "ComplexType %s has unexpected content\n",
2838 type->name);
2839 }
2840 ctxt->container = oldcontainer;
2841 xmlFree(name);
2842 return (type);
2843}
2844
2845
2846/**
2847 * xmlSchemaParseSchema:
2848 * @ctxt: a schema validation context
2849 * @node: a subtree containing XML Schema informations
2850 *
2851 * parse a XML schema definition from a node set
2852 * *WARNING* this interface is highly subject to change
2853 *
2854 * Returns the internal XML Schema structure built from the resource or
2855 * NULL in case of error
2856 */
2857static xmlSchemaPtr
2858xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2859{
2860 xmlSchemaPtr schema = NULL;
2861 xmlSchemaAnnotPtr annot;
2862 xmlNodePtr child = NULL;
2863 xmlChar *val;
2864
2865 if ((ctxt == NULL) || (node == NULL))
2866 return (NULL);
2867
2868 if (IS_SCHEMA(node, "schema")) {
2869 schema = xmlSchemaNewSchema(ctxt);
2870 if (schema == NULL)
2871 return(NULL);
2872 schema->targetNamespace = xmlGetProp(node, BAD_CAST "targetNamespace");
2873 schema->id = xmlGetProp(node, BAD_CAST "id");
2874 schema->version = xmlGetProp(node, BAD_CAST "version");
2875 val = xmlGetProp(node, BAD_CAST "elementFormDefault");
2876 if (val != NULL) {
2877 if (xmlStrEqual(val, BAD_CAST "qualified"))
2878 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
2879 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
2880 xmlSchemaErrorContext(ctxt, schema, node, child);
2881 if ((ctxt != NULL) && (ctxt->error != NULL)) {
2882 ctxt->error(ctxt->userData,
2883 "Invalid value %s for elementFormDefault\n",
2884 val);
2885 }
2886 }
2887 xmlFree(val);
2888 }
2889 val = xmlGetProp(node, BAD_CAST "attributeFormDefault");
2890 if (val != NULL) {
2891 if (xmlStrEqual(val, BAD_CAST "qualified"))
2892 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
2893 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
2894 xmlSchemaErrorContext(ctxt, schema, node, child);
2895 if ((ctxt != NULL) && (ctxt->error != NULL)) {
2896 ctxt->error(ctxt->userData,
2897 "Invalid value %s for elementFormDefault\n",
2898 val);
2899 }
2900 }
2901 xmlFree(val);
2902 }
2903
2904 child = node->children;
2905 while ((IS_SCHEMA(child, "include")) ||
2906 (IS_SCHEMA(child, "import")) ||
2907 (IS_SCHEMA(child, "redefine")) ||
2908 (IS_SCHEMA(child, "annotation"))) {
2909 if (IS_SCHEMA(child, "annotation")) {
2910 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2911 if (schema->annot == NULL)
2912 schema->annot = annot;
2913 else
2914 xmlSchemaFreeAnnot(annot);
2915 } else if (IS_SCHEMA(child, "include")) {
2916 TODO
2917 } else if (IS_SCHEMA(child, "import")) {
Daniel Veillard5a872412002-05-22 06:40:27 +00002918 xmlSchemaParseImport(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002919 } else if (IS_SCHEMA(child, "redefine")) {
2920 TODO
2921 }
2922 child = child->next;
2923 }
2924 while (child != NULL) {
2925 if (IS_SCHEMA(child, "complexType")) {
2926 xmlSchemaParseComplexType(ctxt, schema, child);
2927 child = child->next;
2928 } else if (IS_SCHEMA(child, "simpleType")) {
2929 xmlSchemaParseSimpleType(ctxt, schema, child);
2930 child = child->next;
2931 } else if (IS_SCHEMA(child, "element")) {
2932 xmlSchemaParseElement(ctxt, schema, child, 1);
2933 child = child->next;
2934 } else if (IS_SCHEMA(child, "attribute")) {
2935 xmlSchemaParseAttribute(ctxt, schema, child);
2936 child = child->next;
2937 } else if (IS_SCHEMA(child, "attributeGroup")) {
2938 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2939 child = child->next;
2940 } else if (IS_SCHEMA(child, "group")) {
2941 xmlSchemaParseGroup(ctxt, schema, child);
2942 child = child->next;
2943 } else if (IS_SCHEMA(child, "notation")) {
2944 xmlSchemaParseNotation(ctxt, schema, child);
2945 child = child->next;
2946 } else {
2947 xmlSchemaErrorContext(ctxt, schema, node, child);
2948 if ((ctxt != NULL) && (ctxt->error != NULL))
2949 ctxt->error(ctxt->userData,
2950 "Schemas: unexpected element %s here \n",
2951 child->name);
2952 child = child->next;
2953 }
2954 while (IS_SCHEMA(child, "annotation")) {
2955 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2956 if (schema->annot == NULL)
2957 schema->annot = annot;
2958 else
2959 xmlSchemaFreeAnnot(annot);
2960 child = child->next;
2961 }
2962 }
2963 }
2964#ifdef DEBUG
2965 if (schema == NULL)
2966 xmlGenericError(xmlGenericErrorContext,
2967 "xmlSchemaParse() failed\n");
2968#endif
2969
2970 return (schema);
2971}
2972
2973/************************************************************************
2974 * *
2975 * Validating using Schemas *
2976 * *
2977 ************************************************************************/
2978
2979/************************************************************************
2980 * *
2981 * Reading/Writing Schemas *
2982 * *
2983 ************************************************************************/
2984
2985/**
2986 * xmlSchemaNewParserCtxt:
2987 * @URL: the location of the schema
2988 *
2989 * Create an XML Schemas parse context for that file/resource expected
2990 * to contain an XML Schemas file.
2991 *
2992 * Returns the parser context or NULL in case of error
2993 */
2994xmlSchemaParserCtxtPtr
2995xmlSchemaNewParserCtxt(const char *URL) {
2996 xmlSchemaParserCtxtPtr ret;
2997
2998 if (URL == NULL)
2999 return(NULL);
3000
3001 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3002 if (ret == NULL) {
3003 xmlGenericError(xmlGenericErrorContext,
3004 "Failed to allocate new schama parser context for %s\n", URL);
3005 return (NULL);
3006 }
3007 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3008 ret->URL = xmlStrdup((const xmlChar *)URL);
3009 return (ret);
3010}
3011
3012/**
3013 * xmlSchemaFreeParserCtxt:
3014 * @ctxt: the schema parser context
3015 *
3016 * Free the resources associated to the schema parser context
3017 */
3018void
3019xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) {
3020 if (ctxt == NULL)
3021 return;
3022 if (ctxt->URL != NULL)
3023 xmlFree(ctxt->URL);
3024 xmlFree(ctxt);
3025}
3026
3027/************************************************************************
3028 * *
3029 * Building the content models *
3030 * *
3031 ************************************************************************/
3032/**
3033 * xmlSchemaBuildAContentModel:
3034 * @type: the schema type definition
3035 * @ctxt: the schema parser context
3036 * @name: the element name whose content is being built
3037 *
3038 * Generate the automata sequence needed for that type
3039 */
3040static void
3041xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
3042 xmlSchemaParserCtxtPtr ctxt,
3043 const xmlChar *name) {
3044 if (type == NULL) {
3045 xmlGenericError(xmlGenericErrorContext,
3046 "Found unexpected type = NULL in %s content model\n",
3047 name);
3048 return;
3049 }
3050 switch (type->type) {
3051 case XML_SCHEMA_TYPE_ANY:
3052 /* TODO : handle the namespace too */
3053 /* TODO : make that a specific transition type */
3054 TODO
3055 ctxt->state = xmlAutomataNewTransition(ctxt->am, ctxt->state,
3056 NULL, BAD_CAST "*", NULL);
3057 break;
3058 case XML_SCHEMA_TYPE_ELEMENT: {
3059 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
3060 /* TODO : handle the namespace too */
3061 xmlAutomataStatePtr oldstate = ctxt->state;
3062 if (elem->maxOccurs >= UNBOUNDED) {
3063 if (elem->refDecl != NULL) {
3064 xmlSchemaBuildAContentModel(
3065 (xmlSchemaTypePtr) elem->refDecl,
3066 ctxt, elem->refDecl->name);
3067 } else {
3068 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3069 ctxt->state, NULL, elem->name, type);
3070 }
3071 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
3072 if (elem->minOccurs == 0) {
3073 /* basically an elem* */
3074 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3075 }
3076 } else if (elem->maxOccurs > 1) {
3077 if (elem->refDecl != NULL) {
3078 TODO
3079 xmlSchemaBuildAContentModel(
3080 (xmlSchemaTypePtr) elem->refDecl,
3081 ctxt, elem->refDecl->name);
3082 } else {
3083 ctxt->state = xmlAutomataNewCountTrans(ctxt->am,
3084 ctxt->state, NULL, elem->name,
3085 elem->minOccurs, elem->maxOccurs, type);
3086 }
3087 } else {
3088 if (elem->refDecl != NULL) {
3089 xmlSchemaBuildAContentModel(
3090 (xmlSchemaTypePtr) elem->refDecl,
3091 ctxt, elem->refDecl->name);
3092 } else {
3093 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3094 ctxt->state, NULL, elem->name, type);
3095 }
3096 if (elem->minOccurs == 0) {
3097 /* basically an elem? */
3098 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3099 }
3100 }
3101 break;
3102 }
3103 case XML_SCHEMA_TYPE_SEQUENCE: {
3104 xmlSchemaTypePtr subtypes;
3105
3106 /*
3107 * Simply iterate over the subtypes
3108 */
3109 subtypes = type->subtypes;
3110 while (subtypes != NULL) {
3111 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3112 subtypes = subtypes->next;
3113 }
3114 break;
3115 }
3116 case XML_SCHEMA_TYPE_CHOICE: {
3117 xmlSchemaTypePtr subtypes;
3118 xmlAutomataStatePtr start, end;
3119
3120 start = ctxt->state;
3121 end = xmlAutomataNewState(ctxt->am);
3122
3123 /*
3124 * iterate over the subtypes and remerge the end with an
3125 * epsilon transition
3126 */
Daniel Veillardb509f152002-04-17 16:28:10 +00003127 if (type->maxOccurs == 1) {
3128 subtypes = type->subtypes;
3129 while (subtypes != NULL) {
3130 ctxt->state = start;
3131 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3132 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
3133 subtypes = subtypes->next;
3134 }
3135 } else {
3136 int counter;
3137 xmlAutomataStatePtr hop;
3138
3139 /*
3140 * use a counter to keep track of the number of transtions
3141 * which went through the choice.
3142 */
3143 if (type->minOccurs < 1) {
3144 counter = xmlAutomataNewCounter(ctxt->am, 0,
3145 type->maxOccurs - 1);
3146 } else {
3147 counter = xmlAutomataNewCounter(ctxt->am,
3148 type->minOccurs - 1, type->maxOccurs - 1);
3149 }
3150 hop = xmlAutomataNewState(ctxt->am);
3151
3152 subtypes = type->subtypes;
3153 while (subtypes != NULL) {
3154 ctxt->state = start;
3155 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3156 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
3157 subtypes = subtypes->next;
3158 }
3159 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
3160 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
3161 }
3162 if (type->minOccurs == 0) {
3163 xmlAutomataNewEpsilon(ctxt->am, start, end);
Daniel Veillard4255d502002-04-16 15:50:10 +00003164 }
3165 ctxt->state = end;
3166 break;
3167 }
3168 case XML_SCHEMA_TYPE_ALL: {
Daniel Veillard7646b182002-04-20 06:41:40 +00003169 xmlAutomataStatePtr start;
3170 xmlSchemaTypePtr subtypes;
3171 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard441bc322002-04-20 17:38:48 +00003172 int lax;
Daniel Veillard7646b182002-04-20 06:41:40 +00003173
3174 subtypes = type->subtypes;
3175 if (subtypes == NULL)
3176 break;
3177 start = ctxt->state;
3178 while (subtypes != NULL) {
3179 ctxt->state = start;
3180 elem = (xmlSchemaElementPtr) subtypes;
3181
3182 /* TODO : handle the namespace too */
3183 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state, ctxt->state,
3184 elem->name, elem->minOccurs, elem->maxOccurs,
3185 subtypes);
3186 subtypes = subtypes->next;
3187 }
Daniel Veillard441bc322002-04-20 17:38:48 +00003188 lax = type->minOccurs == 0;
3189 ctxt->state = xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
3190 lax);
Daniel Veillard4255d502002-04-16 15:50:10 +00003191 break;
3192 }
3193 case XML_SCHEMA_TYPE_RESTRICTION:
Daniel Veillardb4398962002-04-19 07:01:55 +00003194 if (type->subtypes != NULL)
Daniel Veillard6231e842002-04-18 11:54:04 +00003195 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3196 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003197 case XML_SCHEMA_TYPE_EXTENSION:
Daniel Veillard6231e842002-04-18 11:54:04 +00003198 if (type->baseType != NULL) {
3199 xmlSchemaTypePtr subtypes;
3200
3201 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
3202 subtypes = type->subtypes;
3203 while (subtypes != NULL) {
3204 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
3205 subtypes = subtypes->next;
3206 }
3207 } else if (type->subtypes != NULL)
3208 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3209 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003210 case XML_SCHEMA_TYPE_GROUP:
3211 case XML_SCHEMA_TYPE_COMPLEX:
3212 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
3213 if (type->subtypes != NULL)
3214 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
3215 break;
3216 default:
3217 xmlGenericError(xmlGenericErrorContext,
3218 "Found unexpected type %d in %s content model\n",
3219 type->type, name);
3220 return;
3221 }
3222}
3223/**
3224 * xmlSchemaBuildContentModel:
3225 * @typeDecl: the schema type definition
3226 * @ctxt: the schema parser context
3227 *
3228 * Fixes the content model of the element.
3229 */
3230static void
3231xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
3232 xmlSchemaParserCtxtPtr ctxt,
3233 const xmlChar *name) {
3234 xmlAutomataStatePtr start;
3235
Daniel Veillard4255d502002-04-16 15:50:10 +00003236 if (elem->contModel != NULL)
3237 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003238 if (elem->subtypes == NULL) {
3239 elem->contentType = XML_SCHEMA_CONTENT_ANY;
Daniel Veillard4255d502002-04-16 15:50:10 +00003240 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00003241 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003242 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
3243 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003244 if (elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC)
3245 return;
3246
3247#ifdef DEBUG_CONTENT
3248 xmlGenericError(xmlGenericErrorContext,
3249 "Building content model for %s\n", name);
3250#endif
3251
Daniel Veillard4255d502002-04-16 15:50:10 +00003252 ctxt->am = xmlNewAutomata();
3253 if (ctxt->am == NULL) {
3254 xmlGenericError(xmlGenericErrorContext,
3255 "Cannot create automata for elem %s\n", name);
3256 return;
3257 }
3258 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
3259 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
3260 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillarde19fc232002-04-22 16:01:24 +00003261 if (!xmlAutomataIsDeterminist(ctxt->am)) {
3262 xmlGenericError(xmlGenericErrorContext,
3263 "Content model of %s is not determinist:\n", name);
3264 elem->contModel = xmlAutomataCompile(ctxt->am);
3265 ctxt->err = XML_SCHEMAS_ERR_NOTDETERMINIST;
3266 } else {
3267 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillard4255d502002-04-16 15:50:10 +00003268#ifdef DEBUG_CONTENT
Daniel Veillarde19fc232002-04-22 16:01:24 +00003269 xmlGenericError(xmlGenericErrorContext,
3270 "Content model of %s:\n", name);
3271 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003272#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00003273 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003274 ctxt->state = NULL;
3275 xmlFreeAutomata(ctxt->am);
3276 ctxt->am = NULL;
3277}
3278
3279/**
3280 * xmlSchemaRefFixupCallback:
3281 * @elem: the schema element context
3282 * @ctxt: the schema parser context
3283 *
3284 * Free the resources associated to the schema parser context
3285 */
3286static void
3287xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
3288 xmlSchemaParserCtxtPtr ctxt,
3289 const xmlChar *name,
3290 ATTRIBUTE_UNUSED const xmlChar *context,
3291 ATTRIBUTE_UNUSED const xmlChar *namespace)
3292{
3293 if ((ctxt == NULL) || (elem == NULL))
3294 return;
3295 if (elem->ref != NULL) {
3296 xmlSchemaElementPtr elemDecl;
3297
3298 if (elem->subtypes != NULL) {
3299 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3300 if ((ctxt != NULL) && (ctxt->error != NULL))
3301 ctxt->error(ctxt->userData,
3302 "Schemas: element %s have both ref and subtype\n",
3303 name);
3304 return;
3305 }
3306 elemDecl = xmlHashLookup2(ctxt->schema->elemDecl,
3307 elem->ref, elem->refNs);
3308
3309 if (elemDecl == NULL) {
3310 if ((ctxt != NULL) && (ctxt->error != NULL))
3311 ctxt->error(ctxt->userData,
3312 "Schemas: element %s ref to %s not found\n",
3313 name, elem->ref);
3314 return;
3315 }
3316 elem->refDecl = elemDecl;
3317 } else if (elem->namedType != NULL) {
3318 xmlSchemaTypePtr typeDecl;
3319
3320 if (elem->subtypes != NULL) {
3321 xmlSchemaErrorContext(ctxt, NULL, elem->node, NULL);
3322 if ((ctxt != NULL) && (ctxt->error != NULL))
3323 ctxt->error(ctxt->userData,
3324 "Schemas: element %s have both type and subtype\n",
3325 name);
3326 return;
3327 }
3328 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
3329 elem->namedTypeNs);
3330
3331 if (typeDecl == NULL) {
3332 if ((ctxt != NULL) && (ctxt->error != NULL))
3333 ctxt->error(ctxt->userData,
3334 "Schemas: element %s type %s not found\n",
3335 name, elem->namedType);
3336 return;
3337 }
3338 elem->subtypes = typeDecl;
3339 }
3340}
3341
3342/**
3343 * xmlSchemaTypeFixup:
3344 * @typeDecl: the schema type definition
3345 * @ctxt: the schema parser context
3346 *
3347 * Fixes the content model of the type.
3348 */
3349static void
3350xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
3351 xmlSchemaParserCtxtPtr ctxt,
3352 const xmlChar *name)
3353{
3354 if (name == NULL)
3355 name = typeDecl->name;
3356 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
3357 switch (typeDecl->type) {
3358 case XML_SCHEMA_TYPE_SIMPLE_CONTENT: {
3359 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3360 typeDecl->contentType = typeDecl->subtypes->contentType;
3361 break;
3362 }
3363 case XML_SCHEMA_TYPE_RESTRICTION: {
3364 if (typeDecl->subtypes != NULL)
3365 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3366
3367 if (typeDecl->base != NULL) {
3368 xmlSchemaTypePtr baseType;
3369
3370 baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3371 typeDecl->baseNs);
3372 if (baseType == NULL) {
3373 if ((ctxt != NULL) && (ctxt->error != NULL))
3374 ctxt->error(ctxt->userData,
3375 "Schemas: type %s base type %s not found\n",
3376 name, typeDecl->base);
3377 }
3378 typeDecl->baseType = baseType;
3379 }
3380 if (typeDecl->subtypes == NULL)
3381 /* 1.1.1 */
3382 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3383 else if ((typeDecl->subtypes->subtypes == NULL) &&
3384 ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3385 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3386 /* 1.1.2 */
3387 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3388 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3389 (typeDecl->subtypes->subtypes == NULL))
3390 /* 1.1.3 */
3391 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3392 else {
3393 /* 1.2 and 2.X are applied at the other layer */
3394 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3395 }
3396 break;
3397 }
3398 case XML_SCHEMA_TYPE_EXTENSION: {
3399 xmlSchemaContentType explicitContentType;
3400 xmlSchemaTypePtr base;
3401
3402 if (typeDecl->base != NULL) {
3403 xmlSchemaTypePtr baseType;
3404
3405 baseType = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3406 typeDecl->baseNs);
3407 if (baseType == NULL) {
3408 if ((ctxt != NULL) && (ctxt->error != NULL))
3409 ctxt->error(ctxt->userData,
3410 "Schemas: type %s base type %s not found\n",
3411 name, typeDecl->base);
3412 }
3413 typeDecl->baseType = baseType;
3414 }
3415 if (typeDecl->subtypes != NULL)
3416 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3417
Daniel Veillard8651f532002-04-17 09:06:27 +00003418 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillard4255d502002-04-16 15:50:10 +00003419 if (typeDecl->subtypes == NULL)
3420 /* 1.1.1 */
3421 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3422 else if ((typeDecl->subtypes->subtypes == NULL) &&
3423 ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_ALL) ||
3424 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SEQUENCE)))
3425 /* 1.1.2 */
3426 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3427 else if ((typeDecl->subtypes->type == XML_SCHEMA_TYPE_CHOICE) &&
3428 (typeDecl->subtypes->subtypes == NULL))
3429 /* 1.1.3 */
3430 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
3431
3432 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
3433 typeDecl->baseNs);
3434 if (base == NULL) {
3435 xmlSchemaErrorContext(ctxt, NULL, typeDecl->node, NULL);
3436 if ((ctxt != NULL) && (ctxt->error != NULL))
3437 ctxt->error(ctxt->userData,
3438 "Schemas: base type %s of type %s not found\n",
3439 typeDecl->base, name);
3440 return;
3441 }
3442 xmlSchemaTypeFixup(base, ctxt, NULL);
3443 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
3444 /* 2.1 */
3445 typeDecl->contentType = base->contentType;
3446 } else if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
3447 /* 2.2 imbitable ! */
3448 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3449 } else {
3450 /* 2.3 imbitable pareil ! */
3451 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3452 }
3453 break;
3454 }
3455 case XML_SCHEMA_TYPE_COMPLEX: {
3456 if (typeDecl->subtypes == NULL) {
3457 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3458 } else {
3459 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3460 typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3461 else {
3462 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3463 typeDecl->contentType = typeDecl->subtypes->contentType;
3464 }
3465 }
3466 break;
3467 }
3468 case XML_SCHEMA_TYPE_COMPLEX_CONTENT: {
3469 if (typeDecl->subtypes == NULL) {
3470 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
3471 } else {
3472 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
3473 typeDecl->contentType = XML_SCHEMA_CONTENT_MIXED;
3474 else {
3475 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
3476 typeDecl->contentType = typeDecl->subtypes->contentType;
3477 }
3478 }
3479 break;
3480 }
3481 case XML_SCHEMA_TYPE_SEQUENCE:
3482 case XML_SCHEMA_TYPE_GROUP:
3483 case XML_SCHEMA_TYPE_ALL:
3484 case XML_SCHEMA_TYPE_CHOICE:
3485 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
3486 break;
3487 case XML_SCHEMA_TYPE_BASIC:
3488 case XML_SCHEMA_TYPE_ANY:
3489 case XML_SCHEMA_TYPE_FACET:
3490 case XML_SCHEMA_TYPE_SIMPLE:
3491 case XML_SCHEMA_TYPE_UR:
3492 case XML_SCHEMA_TYPE_ELEMENT:
3493 case XML_SCHEMA_TYPE_ATTRIBUTE:
3494 case XML_SCHEMA_TYPE_NOTATION:
3495 case XML_SCHEMA_TYPE_LIST:
3496 case XML_SCHEMA_TYPE_UNION:
3497 case XML_SCHEMA_FACET_MININCLUSIVE:
3498 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3499 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3500 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
3501 case XML_SCHEMA_FACET_TOTALDIGITS:
3502 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3503 case XML_SCHEMA_FACET_PATTERN:
3504 case XML_SCHEMA_FACET_ENUMERATION:
3505 case XML_SCHEMA_FACET_WHITESPACE:
3506 case XML_SCHEMA_FACET_LENGTH:
3507 case XML_SCHEMA_FACET_MAXLENGTH:
3508 case XML_SCHEMA_FACET_MINLENGTH:
3509 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
3510 break;
3511 }
3512 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003513#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00003514 if (typeDecl->node != NULL) {
3515 xmlGenericError(xmlGenericErrorContext,
3516 "Type of %s : %s:%d :", name, typeDecl->node->doc->URL,
3517 xmlGetLineNo(typeDecl->node));
3518 } else {
3519 xmlGenericError(xmlGenericErrorContext,
3520 "Type of %s :", name);
3521 }
Daniel Veillard8651f532002-04-17 09:06:27 +00003522 switch (typeDecl->contentType) {
3523 case XML_SCHEMA_CONTENT_SIMPLE:
3524 xmlGenericError(xmlGenericErrorContext,
3525 "simple\n"); break;
3526 case XML_SCHEMA_CONTENT_ELEMENTS:
3527 xmlGenericError(xmlGenericErrorContext,
3528 "elements\n"); break;
3529 case XML_SCHEMA_CONTENT_UNKNOWN:
3530 xmlGenericError(xmlGenericErrorContext,
3531 "unknown !!!\n"); break;
3532 case XML_SCHEMA_CONTENT_EMPTY:
3533 xmlGenericError(xmlGenericErrorContext,
3534 "empty\n"); break;
3535 case XML_SCHEMA_CONTENT_MIXED:
3536 xmlGenericError(xmlGenericErrorContext,
3537 "mixed\n"); break;
3538 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
3539 xmlGenericError(xmlGenericErrorContext,
3540 "mixed or elems\n"); break;
3541 case XML_SCHEMA_CONTENT_BASIC:
3542 xmlGenericError(xmlGenericErrorContext,
3543 "basic\n"); break;
3544 default:
3545 xmlGenericError(xmlGenericErrorContext,
3546 "not registered !!!\n"); break;
3547 }
3548#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003549}
3550
3551/**
3552 * xmlSchemaCheckDefaults:
3553 * @typeDecl: the schema type definition
3554 * @ctxt: the schema parser context
3555 *
3556 * Checks the default values types, especially for facets
3557 */
3558static void
3559xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
3560 xmlSchemaParserCtxtPtr ctxt,
3561 const xmlChar *name)
3562{
3563 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
3564 if (name == NULL)
3565 name = typeDecl->name;
3566 if (nonNegativeIntegerType == NULL) {
3567 nonNegativeIntegerType = xmlSchemaGetPredefinedType(
3568 BAD_CAST "nonNegativeInteger", xmlSchemaNs);
3569 }
3570 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
3571 if (typeDecl->facets != NULL) {
3572 xmlSchemaFacetPtr facet = typeDecl->facets;
3573 while (facet != NULL) {
3574 switch (facet->type) {
3575 case XML_SCHEMA_FACET_MININCLUSIVE:
3576 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3577 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3578 case XML_SCHEMA_FACET_MAXEXCLUSIVE: {
3579 /*
3580 * Okay we need to validate the value
3581 * at that point.
3582 */
3583 xmlSchemaValidCtxtPtr vctxt;
3584
3585 vctxt = xmlSchemaNewValidCtxt(NULL);
3586 if (vctxt == NULL)
3587 break;
3588 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3589 facet->value);
3590 facet->val = vctxt->value;
3591 vctxt->value = NULL;
3592 if (facet->val == NULL) {
3593 /* error code */
3594 xmlSchemaErrorContext(ctxt, NULL,
3595 facet->node, NULL);
3596 ctxt->error(ctxt->userData,
3597 "Schemas: type %s facet value %s invalid\n",
3598 name, facet->value);
3599 }
3600 xmlSchemaFreeValidCtxt(vctxt);
3601 break;
3602 }
3603 case XML_SCHEMA_FACET_ENUMERATION: {
3604 /*
3605 * Okay we need to validate the value
3606 * at that point.
3607 */
3608 xmlSchemaValidCtxtPtr vctxt;
3609 int ret;
3610
3611 vctxt = xmlSchemaNewValidCtxt(NULL);
3612 if (vctxt == NULL)
3613 break;
3614 ret = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
3615 facet->value);
3616 if (ret != 0) {
3617 xmlSchemaErrorContext(ctxt, NULL,
3618 facet->node, NULL);
3619 ctxt->error(ctxt->userData,
3620 "Schemas: type %s enumeration value %s invalid\n",
3621 name, facet->value);
3622 }
3623 xmlSchemaFreeValidCtxt(vctxt);
3624 break;
3625 }
3626 case XML_SCHEMA_FACET_PATTERN:
3627 facet->regexp = xmlRegexpCompile(facet->value);
3628 if (facet->regexp == NULL) {
3629 /* error code */
3630 ctxt->error(ctxt->userData,
3631 "Schemas: type %s facet regexp %s invalid\n",
3632 name, facet->value);
3633 }
3634 break;
3635 case XML_SCHEMA_FACET_TOTALDIGITS:
3636 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3637 case XML_SCHEMA_FACET_LENGTH:
3638 case XML_SCHEMA_FACET_MAXLENGTH:
3639 case XML_SCHEMA_FACET_MINLENGTH: {
3640 int ret;
3641
3642 ret = xmlSchemaValidatePredefinedType(
3643 nonNegativeIntegerType, facet->value,
3644 &facet->val);
3645 if (ret != 0) {
3646 /* error code */
3647 xmlSchemaErrorContext(ctxt, NULL,
3648 facet->node, NULL);
3649 ctxt->error(ctxt->userData,
3650 "Schemas: type %s facet value %s invalid\n",
3651 name, facet->value);
3652 }
3653 break;
3654 }
3655 case XML_SCHEMA_FACET_WHITESPACE: {
3656 if (xmlStrEqual(facet->value, BAD_CAST"preserve")) {
3657 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
3658 } else if (xmlStrEqual(facet->value,
3659 BAD_CAST"replace")) {
3660 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
3661 } else if (xmlStrEqual(facet->value,
3662 BAD_CAST"collapse")) {
3663 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
3664 } else {
3665 xmlSchemaErrorContext(ctxt, NULL,
3666 facet->node, NULL);
3667 ctxt->error(ctxt->userData,
3668 "Schemas: type %s whiteSpace value %s invalid\n",
3669 name, facet->value);
3670 }
3671 }
3672 default:
3673 break;
3674 }
3675 facet = facet->next;
3676 }
3677 }
3678 }
3679}
3680
3681/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00003682 * xmlSchemaAttrGrpFixup:
3683 * @attrgrpDecl: the schema attribute definition
3684 * @ctxt: the schema parser context
3685 * @name: the attribute name
3686 *
3687 * Fixes finish doing the computations on the attributes definitions
3688 */
3689static void
3690xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
3691 xmlSchemaParserCtxtPtr ctxt,
3692 const xmlChar *name)
3693{
3694 if (name == NULL)
3695 name = attrgrpDecl->name;
3696 if (attrgrpDecl->attributes != NULL)
3697 return;
3698 if (attrgrpDecl->ref != NULL) {
3699 xmlSchemaAttributeGroupPtr ref;
3700
3701 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
3702 attrgrpDecl->refNs);
3703 if (ref == NULL) {
3704 if ((ctxt != NULL) && (ctxt->error != NULL))
3705 ctxt->error(ctxt->userData,
3706 "Schemas: attribute group %s reference %s not found\n",
3707 name, attrgrpDecl->ref);
3708 return;
3709 }
3710 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
3711 attrgrpDecl->attributes = ref->attributes;
3712 } else {
3713 if ((ctxt != NULL) && (ctxt->error != NULL))
3714 ctxt->error(ctxt->userData,
3715 "Schemas: attribute %s has no attributes nor reference\n",
3716 name);
3717 }
3718}
3719
3720/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003721 * xmlSchemaAttrFixup:
3722 * @attrDecl: the schema attribute definition
3723 * @ctxt: the schema parser context
3724 * @name: the attribute name
3725 *
3726 * Fixes finish doing the computations on the attributes definitions
3727 */
3728static void
3729xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
3730 xmlSchemaParserCtxtPtr ctxt,
3731 const xmlChar *name)
3732{
3733 if (name == NULL)
3734 name = attrDecl->name;
3735 if (attrDecl->subtypes != NULL)
3736 return;
3737 if (attrDecl->typeName != NULL) {
3738 xmlSchemaTypePtr type;
3739
3740 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
3741 attrDecl->typeNs);
3742 if (type == NULL) {
3743 if ((ctxt != NULL) && (ctxt->error != NULL))
3744 ctxt->error(ctxt->userData,
3745 "Schemas: attribute %s type %s not found\n",
3746 name, attrDecl->typeName);
3747 }
3748 attrDecl->subtypes = type;
3749 } else if (attrDecl->ref != NULL) {
3750 xmlSchemaAttributePtr ref;
3751
3752 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
3753 attrDecl->refNs);
3754 if (ref == NULL) {
3755 if ((ctxt != NULL) && (ctxt->error != NULL))
3756 ctxt->error(ctxt->userData,
3757 "Schemas: attribute %s reference %s not found\n",
3758 name, attrDecl->ref);
3759 return;
3760 }
3761 xmlSchemaAttrFixup(ref, ctxt, NULL);
3762 attrDecl->subtypes = ref->subtypes;
3763 } else {
3764 if ((ctxt != NULL) && (ctxt->error != NULL))
3765 ctxt->error(ctxt->userData,
3766 "Schemas: attribute %s has no type nor reference\n",
3767 name);
3768 }
3769}
3770
3771/**
3772 * xmlSchemaParse:
3773 * @ctxt: a schema validation context
3774 * @URL: the location of the schema
3775 *
3776 * Load, XML parse a schema definition resource and build an internal
3777 * XML Shema struture which can be used to validate instances.
3778 * *WARNING* this interface is highly subject to change
3779 *
3780 * Returns the internal XML Schema structure built from the resource or
3781 * NULL in case of error
3782 */
3783xmlSchemaPtr
3784xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
3785{
3786 xmlSchemaPtr ret = NULL;
3787 xmlDocPtr doc;
3788 xmlNodePtr root, cur, delete;
3789
3790 xmlSchemaInitTypes();
3791
3792 if ((ctxt == NULL) || (ctxt->URL == NULL))
3793 return (NULL);
3794
3795 ctxt->counter = 0;
3796 ctxt->container = NULL;
3797
3798 /*
3799 * First step is to parse the input document into an DOM/Infoset
3800 */
3801 doc = xmlParseFile((const char *) ctxt->URL);
3802 if (doc == NULL) {
3803 if (ctxt->error != NULL)
3804 ctxt->error(ctxt->userData,
3805 "xmlSchemaParse: could not load %s\n", ctxt->URL);
3806 return (NULL);
3807 }
3808
3809 /*
3810 * Then extract the root and Schema parse it
3811 */
3812 root = xmlDocGetRootElement(doc);
3813 if (root == NULL) {
3814 if (ctxt->error != NULL)
3815 ctxt->error(ctxt->userData, "xmlSchemaParse: %s is empty\n",
3816 ctxt->URL);
3817 return (NULL);
3818 }
3819
3820 /*
3821 * Remove all the blank text nodes
3822 */
3823 delete = NULL;
3824 cur = root;
3825 while (cur != NULL) {
3826 if (delete != NULL) {
3827 xmlUnlinkNode(delete);
3828 xmlFreeNode(delete);
3829 delete = NULL;
3830 }
3831 if (cur->type == XML_TEXT_NODE) {
3832 if (IS_BLANK_NODE(cur)) {
3833 if (xmlNodeGetSpacePreserve(cur) != 1) {
3834 delete = cur;
3835 }
3836 }
3837 } else if ((cur->type != XML_ELEMENT_NODE) &&
3838 (cur->type != XML_CDATA_SECTION_NODE)) {
3839 delete = cur;
3840 goto skip_children;
3841 }
3842
3843 /*
3844 * Skip to next node
3845 */
3846 if (cur->children != NULL) {
3847 if ((cur->children->type != XML_ENTITY_DECL) &&
3848 (cur->children->type != XML_ENTITY_REF_NODE) &&
3849 (cur->children->type != XML_ENTITY_NODE)) {
3850 cur = cur->children;
3851 continue;
3852 }
3853 }
3854skip_children:
3855 if (cur->next != NULL) {
3856 cur = cur->next;
3857 continue;
3858 }
3859
3860 do {
3861 cur = cur->parent;
3862 if (cur == NULL)
3863 break;
3864 if (cur == root) {
3865 cur = NULL;
3866 break;
3867 }
3868 if (cur->next != NULL) {
3869 cur = cur->next;
3870 break;
3871 }
3872 } while (cur != NULL);
3873 }
3874 if (delete != NULL) {
3875 xmlUnlinkNode(delete);
3876 xmlFreeNode(delete);
3877 delete = NULL;
3878 }
3879
3880 /*
3881 * Then do the parsing for good
3882 */
3883 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillardb4398962002-04-19 07:01:55 +00003884 if (ret == NULL)
3885 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003886 ret->doc = doc;
3887
3888 /*
3889 * Then fix all the references.
3890 */
3891 ctxt->schema = ret;
3892 xmlHashScanFull(ret->elemDecl,
3893 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
3894
3895 /*
3896 * Then fixup all types properties
3897 */
3898 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
3899
3900 /*
3901 * Then build the content model for all elements
3902 */
3903 xmlHashScan(ret->elemDecl,
3904 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
3905
3906 /*
3907 * Then check the defaults part of the type like facets values
3908 */
3909 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt);
3910
3911 /*
3912 * Then fixup all attributes declarations
3913 */
3914 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
3915
Daniel Veillard13e04c62002-04-23 17:51:29 +00003916 /*
3917 * Then fixup all attributes group declarations
3918 */
3919 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup, ctxt);
3920
Daniel Veillard4255d502002-04-16 15:50:10 +00003921 return (ret);
3922}
3923
3924/**
3925 * xmlSchemaParse:
3926 * @ctxt: a schema validation context
3927 * @URL: the location of the schema
3928 *
3929 * Load, XML parse a schema definition resource and build an internal
3930 * XML Shema struture which can be used to validate instances.
3931 * *WARNING* this interface is highly subject to change
3932 *
3933 * Returns the internal XML Schema structure built from the resource or
3934 * NULL in case of error
3935 */
3936void
3937xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
3938 xmlSchemaValidityErrorFunc err,
3939 xmlSchemaValidityWarningFunc warn, void *ctx) {
3940 if (ctxt == NULL)
3941 return;
3942 ctxt->error = err;
3943 ctxt->warning = warn;
3944 ctxt->userData = ctx;
3945}
3946
3947/************************************************************************
3948 * *
3949 * Simple type validation *
3950 * *
3951 ************************************************************************/
3952
3953/**
3954 * xmlSchemaValidateSimpleValue:
3955 * @ctxt: a schema validation context
3956 * @type: the type declaration
3957 * @value: the value to validate
3958 *
3959 * Validate a value against a simple type
3960 *
3961 * Returns 0 if the value is valid, a positive error code
3962 * number otherwise and -1 in case of internal or API error.
3963 */
3964static int
3965xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
3966 xmlSchemaTypePtr type,
3967 xmlChar *value) {
3968 int ret = 0;
3969 /*
3970 * First normalize the value accordingly to Schema Datatype
3971 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
3972 */
3973 /*
3974 * Then check the normalized value against the lexical space of the
3975 * type.
3976 */
3977 if (type->type == XML_SCHEMA_TYPE_BASIC) {
3978 if (ctxt->value != NULL) {
3979 xmlSchemaFreeValue(ctxt->value);
3980 ctxt->value = NULL;
3981 }
3982 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
3983 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
3984 xmlSchemaTypePtr base;
3985 xmlSchemaFacetPtr facet;
3986 int tmp;
3987
3988 base = type->baseType;
3989 if (base != NULL) {
3990 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
3991 } else if (type->subtypes != NULL) {
3992
3993 }
3994 /*
3995 * Do not validate facets when working on building the Schemas
3996 */
3997 if (ctxt->schema != NULL) {
3998 if (ret == 0) {
3999 facet = type->facets;
Daniel Veillard88c58912002-04-23 07:12:20 +00004000 if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) &&
4001 (facet != NULL) &&
4002 (facet->type == XML_SCHEMA_FACET_ENUMERATION)) {
4003 while (facet != NULL) {
4004 ret = 1;
4005
4006 tmp = xmlSchemaValidateFacet(base, facet, value,
4007 ctxt->value);
4008 if (tmp == 0) {
4009 ret = 0;
4010 break;
4011 }
4012 facet = facet->next;
4013 }
4014 } else {
4015 while (facet != NULL) {
4016 tmp = xmlSchemaValidateFacet(base, facet, value,
4017 ctxt->value);
4018 if (tmp != 0)
4019 ret = tmp;
4020 facet = facet->next;
4021 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004022 }
4023 }
4024 }
4025 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
4026 xmlSchemaTypePtr base;
4027
4028 base = type->subtypes;
4029 if (base != NULL) {
4030 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4031 } else {
4032 TODO
4033 }
4034 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
4035 xmlSchemaTypePtr base;
4036 xmlChar *cur, *end, tmp;
4037 int ret2;
4038
4039 base = type->subtypes;
4040 if (base == NULL) {
4041 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4042 if (ctxt->error != NULL) {
4043 xmlSchemaErrorContext(NULL, ctxt->schema, type->node, NULL);
4044 ctxt->error(ctxt->userData,
4045 "Internal: List type %s has no base type\n",
4046 type->name);
4047 }
4048 return(-1);
4049 }
4050 cur = value;
4051 do {
4052 while (IS_BLANK(*cur)) cur++;
4053 end = cur;
4054 while ((*end != 0) && (!(IS_BLANK(*end)))) end++;
4055 if (end == cur)
4056 break;
4057 tmp = *end;
4058 *end = 0;
4059 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, cur);
4060 if (ret2 != 0)
4061 ret = 1;
4062 *end = tmp;
4063 cur = end;
4064 } while (*cur != 0);
4065 } else {
4066 TODO
4067 }
4068 return(ret);
4069}
4070
4071/************************************************************************
4072 * *
4073 * DOM Validation code *
4074 * *
4075 ************************************************************************/
4076
4077static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
4078 xmlNodePtr node);
4079static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
4080 xmlNodePtr elem, xmlSchemaAttributePtr attributes);
4081static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
4082 xmlNodePtr elem, xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type);
4083
4084/**
4085 * xmlSchemaRegisterAttributes:
4086 * @ctxt: a schema validation context
4087 * @attrs: a list of attributes
4088 *
4089 * Register the list of attributes as the set to be validated on that element
4090 *
4091 * Returns -1 in case of error, 0 otherwise
4092 */
4093static int
4094xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt,
4095 xmlAttrPtr attrs) {
4096 while (attrs != NULL) {
Daniel Veillard441bc322002-04-20 17:38:48 +00004097 if ((attrs->ns != NULL) &&
4098 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
4099 attrs = attrs->next;
4100 continue;
4101 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004102 if (ctxt->attrNr >= ctxt->attrMax) {
4103 xmlSchemaAttrStatePtr tmp;
4104
4105 ctxt->attrMax *= 2;
4106 tmp = (xmlSchemaAttrStatePtr)
4107 xmlRealloc(ctxt->attr, ctxt->attrMax *
4108 sizeof(xmlSchemaAttrState));
4109 if (tmp == NULL) {
4110 ctxt->attrMax /= 2;
4111 return(-1);
4112 }
4113 ctxt->attr = tmp;
4114 }
4115 ctxt->attr[ctxt->attrNr].attr = attrs;
4116 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
4117 ctxt->attrNr++;
4118 attrs = attrs->next;
4119 }
4120 return(0);
4121}
4122
4123/**
4124 * xmlSchemaCheckAttributes:
4125 * @ctxt: a schema validation context
4126 * @node: the node carrying it.
4127 *
4128 * Check that the registered set of attributes on the current node
4129 * has been properly validated.
4130 *
4131 * Returns 0 if validity constraints are met, 1 otherwise.
4132 */
4133static int
4134xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4135 int ret = 0;
4136 int i;
4137
4138 for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
4139 if (ctxt->attr[i].attr == NULL)
4140 break;
4141 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
4142 ret = 1;
4143 ctxt->err = XML_SCHEMAS_ERR_ATTRUNKNOWN;
4144 if (ctxt->error != NULL)
4145 ctxt->error(ctxt->userData,
4146 "Attribute %s on %s is unknown\n",
4147 ctxt->attr[i].attr->name,
4148 node->name);
4149 }
4150 }
4151 return(ret);
4152}
4153
4154/**
4155 * xmlSchemaValidateSimpleContent:
4156 * @ctxt: a schema validation context
4157 * @elem: an element
4158 * @type: the type declaration
4159 *
4160 * Validate the content of an element expected to be a simple type
4161 *
4162 * Returns 0 if the element is schemas valid, a positive error code
4163 * number otherwise and -1 in case of internal or API error.
4164 */
4165static int
4166xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
4167 ATTRIBUTE_UNUSED xmlNodePtr node) {
4168 xmlNodePtr child;
4169 xmlSchemaTypePtr type, base;
4170 xmlChar *value;
4171 int ret = 0, tmp;
4172
4173 child = ctxt->node;
4174 type = ctxt->type;
4175
4176 /*
4177 * Validation Rule: Element Locally Valid (Type): 3.1.3
4178 */
4179 value = xmlNodeGetContent(child);
4180 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
4181 switch (type->type) {
4182 case XML_SCHEMA_TYPE_RESTRICTION: {
4183 xmlSchemaFacetPtr facet;
4184
4185 base = type->baseType;
4186 if (base != NULL) {
4187 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
4188 } else {
4189 TODO
4190 }
4191 if (ret == 0) {
4192 facet = type->facets;
4193 while (facet != NULL) {
4194 tmp = xmlSchemaValidateFacet(base, facet, value,
4195 ctxt->value);
4196 if (tmp != 0)
4197 ret = tmp;
4198 facet = facet->next;
4199 }
4200 }
4201 break;
4202 }
4203 default:
4204 TODO
4205 }
4206 if (value != NULL)
4207 xmlFree(value);
4208
4209 return(ret);
4210}
4211
4212/**
4213 * xmlSchemaValidateCheckNodeList
4214 * @nodelist: the list of nodes
4215 *
4216 * Check the node list is only made of text nodes and entities pointing
4217 * to text nodes
4218 *
4219 * Returns 1 if true, 0 if false and -1 in case of error
4220 */
4221static int
4222xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist) {
4223 while (nodelist != NULL) {
4224 if (nodelist->type == XML_ENTITY_REF_NODE) {
4225 TODO /* implement recursion in the entity content */
4226 }
4227 if ((nodelist->type != XML_TEXT_NODE) &&
4228 (nodelist->type != XML_COMMENT_NODE) &&
4229 (nodelist->type != XML_PI_NODE) &&
4230 (nodelist->type != XML_PI_NODE)) {
4231 return(0);
4232 }
4233 nodelist = nodelist->next;
4234 }
4235 return(1);
4236}
4237
4238/**
4239 * xmlSchemaSkipIgnored:
4240 * @ctxt: a schema validation context
4241 * @type: the current type context
4242 * @node: the top node.
4243 *
4244 * Skip ignorable nodes in that context
4245 *
4246 * Returns the new sibling
4247 * number otherwise and -1 in case of internal or API error.
4248 */
4249static xmlNodePtr
4250xmlSchemaSkipIgnored(ATTRIBUTE_UNUSED xmlSchemaValidCtxtPtr ctxt,
4251 xmlSchemaTypePtr type,
4252 xmlNodePtr node) {
4253 int mixed = 0;
4254 /*
4255 * TODO complete and handle entities
4256 */
4257 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
4258 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
4259 while ((node != NULL) &&
4260 ((node->type == XML_COMMENT_NODE) ||
4261 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
4262 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
4263 (node->type == XML_TEXT_NODE) &&
4264 (IS_BLANK_NODE(node)))))) {
4265 node = node->next;
4266 }
4267 return(node);
4268}
4269
4270/**
4271 * xmlSchemaValidateCallback:
4272 * @ctxt: a schema validation context
4273 * @name: the name of the element detected (might be NULL)
4274 * @type: the type
4275 *
4276 * A transition has been made in the automata associated to an element
4277 * content model
4278 */
4279static void
4280xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
4281 ATTRIBUTE_UNUSED const xmlChar *name,
4282 xmlSchemaTypePtr type,
4283 xmlNodePtr node) {
4284 xmlSchemaTypePtr oldtype = ctxt->type;
4285 xmlNodePtr oldnode = ctxt->node;
4286#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00004287 xmlGenericError(xmlGenericErrorContext,
4288 "xmlSchemaValidateCallback: %s, %s, %s\n",
4289 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004290#endif
4291 ctxt->type = type;
4292 ctxt->node = node;
4293 xmlSchemaValidateContent(ctxt, node);
4294 ctxt->type = oldtype;
4295 ctxt->node = oldnode;
4296}
4297
4298
4299#if 0
4300/**
4301 * xmlSchemaValidateSimpleRestrictionType:
4302 * @ctxt: a schema validation context
4303 * @node: the top node.
4304 *
4305 * Validate the content of a restriction type.
4306 *
4307 * Returns 0 if the element is schemas valid, a positive error code
4308 * number otherwise and -1 in case of internal or API error.
4309 */
4310static int
4311xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
4312 xmlNodePtr node)
4313{
4314 xmlNodePtr child;
4315 xmlSchemaTypePtr type;
4316 int ret;
4317
4318 child = ctxt->node;
4319 type = ctxt->type;
4320
4321 if ((ctxt == NULL) || (type == NULL)) {
4322 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4323 if (ctxt->error != NULL)
4324 ctxt->error(ctxt->userData,
4325 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
4326 node->name);
4327 return (-1);
4328 }
4329 /*
4330 * Only text and text based entities references shall be found there
4331 */
4332 ret = xmlSchemaValidateCheckNodeList(child);
4333 if (ret < 0) {
4334 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4335 if (ctxt->error != NULL)
4336 ctxt->error(ctxt->userData,
4337 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4338 node->name);
4339 return (-1);
4340 } else if (ret == 0) {
4341 ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4342 if (ctxt->error != NULL)
4343 ctxt->error(ctxt->userData,
4344 "Element %s content is not a simple type\n",
4345 node->name);
4346 return (-1);
4347 }
4348 ctxt->type = type->subtypes;
4349 xmlSchemaValidateContent(ctxt, node);
4350 ctxt->type = type;
4351 return (ret);
4352}
4353#endif
4354
4355/**
4356 * xmlSchemaValidateSimpleType:
4357 * @ctxt: a schema validation context
4358 * @node: the top node.
4359 *
4360 * Validate the content of an simple type.
4361 *
4362 * Returns 0 if the element is schemas valid, a positive error code
4363 * number otherwise and -1 in case of internal or API error.
4364 */
4365static int
4366xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4367 xmlNodePtr child;
4368 xmlSchemaTypePtr type;
4369 xmlAttrPtr attr;
4370 int ret;
4371
4372 child = ctxt->node;
4373 type = ctxt->type;
4374
4375 if ((ctxt == NULL) || (type == NULL)) {
4376 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4377 if (ctxt->error != NULL)
4378 ctxt->error(ctxt->userData,
4379 "Internal error: xmlSchemaValidateSimpleType %s\n",
4380 node->name);
4381 return(-1);
4382 }
4383 /*
4384 * Only text and text based entities references shall be found there
4385 */
4386 ret = xmlSchemaValidateCheckNodeList(child);
4387 if (ret < 0) {
4388 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4389 if (ctxt->error != NULL)
4390 ctxt->error(ctxt->userData,
4391 "Internal error: xmlSchemaValidateSimpleType %s content\n",
4392 node->name);
4393 return(-1);
4394 } else if (ret == 0) {
4395 ctxt->err = XML_SCHEMAS_ERR_NOTSIMPLE;
4396 if (ctxt->error != NULL)
4397 ctxt->error(ctxt->userData,
4398 "Element %s content is not a simple type\n",
4399 node->name);
4400 return(-1);
4401 }
4402 /*
4403 * Validation Rule: Element Locally Valid (Type): 3.1.1
4404 */
4405 attr = node->properties;
4406 while (attr != NULL) {
4407 if ((attr->ns == NULL) ||
4408 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
4409 ((!xmlStrEqual(attr->name, BAD_CAST"type")) &&
4410 (!xmlStrEqual(attr->name, BAD_CAST"nil")) &&
4411 (!xmlStrEqual(attr->name, BAD_CAST"schemasLocation")) &&
4412 (!xmlStrEqual(attr->name, BAD_CAST"noNamespaceSchemaLocation")))) {
4413 ctxt->err = XML_SCHEMAS_ERR_INVALIDATTR;
4414 if (ctxt->error != NULL)
4415 ctxt->error(ctxt->userData,
4416 "Element %s: attribute %s should not be present\n",
4417 child->name, attr->name);
4418 return(ctxt->err);
4419 }
4420 }
4421
4422 ctxt->type = type->subtypes;
4423 ret = xmlSchemaValidateSimpleContent(ctxt, node);
4424 ctxt->type = type;
4425 return(ret);
4426}
4427
4428/**
4429 * xmlSchemaValidateElementType:
4430 * @ctxt: a schema validation context
4431 * @node: the top node.
4432 *
4433 * Validate the content of an element type.
4434 * Validation Rule: Element Locally Valid (Complex Type)
4435 *
4436 * Returns 0 if the element is schemas valid, a positive error code
4437 * number otherwise and -1 in case of internal or API error.
4438 */
4439static int
4440xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4441 xmlNodePtr child;
4442 xmlSchemaTypePtr type;
4443 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
4444 xmlSchemaElementPtr decl;
4445 int ret, attrBase;
4446
4447 oldregexp = ctxt->regexp;
4448
4449 child = ctxt->node;
4450 type = ctxt->type;
4451
4452 if ((ctxt == NULL) || (type == NULL)) {
4453 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4454 if (ctxt->error != NULL)
4455 ctxt->error(ctxt->userData,
4456 "Internal error: xmlSchemaValidateElementType\n",
4457 node->name);
4458 return(-1);
4459 }
4460 if (child == NULL) {
4461 if (type->minOccurs > 0) {
4462 ctxt->err = XML_SCHEMAS_ERR_MISSING;
4463 if (ctxt->error != NULL)
4464 ctxt->error(ctxt->userData,
4465 "Element %s: missing child %s\n",
4466 node->name, type->name);
4467 }
4468 return(ctxt->err);
4469 }
4470
4471 /*
4472 * Verify the element matches
4473 */
4474 if (!xmlStrEqual(child->name, type->name)) {
4475 ctxt->err = XML_SCHEMAS_ERR_WRONGELEM;
4476 if (ctxt->error != NULL)
4477 ctxt->error(ctxt->userData,
4478 "Element %s: missing child %s found %s\n",
4479 node->name, type->name, child->name);
4480 return(ctxt->err);
4481 }
4482 /*
4483 * Verify the attributes
4484 */
4485 attrBase = ctxt->attrBase;
4486 ctxt->attrBase = ctxt->attrNr;
4487 xmlSchemaRegisterAttributes(ctxt, child->properties);
4488 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
4489 /*
4490 * Verify the element content recursively
4491 */
4492 decl = (xmlSchemaElementPtr) type;
4493 oldregexp = ctxt->regexp;
4494 if (decl->contModel != NULL) {
4495 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
4496 (xmlRegExecCallbacks) xmlSchemaValidateCallback,
4497 ctxt);
4498#ifdef DEBUG_AUTOMATA
4499 xmlGenericError(xmlGenericErrorContext,
4500 "====> %s\n", node->name);
4501#endif
4502 }
4503 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr)type,
4504 type->subtypes);
4505
4506 if (decl->contModel != NULL) {
4507 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
4508#ifdef DEBUG_AUTOMATA
4509 xmlGenericError(xmlGenericErrorContext,
4510 "====> %s : %d\n", node->name, ret);
4511#endif
4512 if (ret == 0) {
Daniel Veillard8651f532002-04-17 09:06:27 +00004513 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
Daniel Veillard4255d502002-04-16 15:50:10 +00004514 if (ctxt->error != NULL)
4515 ctxt->error(ctxt->userData, "Element %s content check failed\n",
4516 node->name);
4517 } else if (ret < 0) {
Daniel Veillard8651f532002-04-17 09:06:27 +00004518 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
Daniel Veillard4255d502002-04-16 15:50:10 +00004519 if (ctxt->error != NULL)
4520 ctxt->error(ctxt->userData, "Element %s content check failure\n",
4521 node->name);
4522#ifdef DEBUG_CONTENT
4523 } else {
4524 xmlGenericError(xmlGenericErrorContext,
4525 "Element %s content check succeeded\n", node->name);
4526
4527#endif
4528 }
4529 xmlRegFreeExecCtxt(ctxt->regexp);
4530 }
4531 /*
4532 * Verify that all attributes were Schemas-validated
4533 */
4534 xmlSchemaCheckAttributes(ctxt, node);
4535 ctxt->attrNr = ctxt->attrBase;
4536 ctxt->attrBase = attrBase;
4537
4538 ctxt->regexp = oldregexp;
4539
4540 ctxt->node = child;
4541 ctxt->type = type;
4542 return(ctxt->err);
4543}
4544
4545/**
4546 * xmlSchemaValidateBasicType:
4547 * @ctxt: a schema validation context
4548 * @node: the top node.
4549 *
4550 * Validate the content of an element expected to be a basic type type
4551 *
4552 * Returns 0 if the element is schemas valid, a positive error code
4553 * number otherwise and -1 in case of internal or API error.
4554 */
4555static int
4556xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4557 int ret;
4558 xmlNodePtr child, cur;
4559 xmlSchemaTypePtr type;
4560 xmlChar *value; /* lexical representation */
4561
4562 child = ctxt->node;
4563 type = ctxt->type;
4564
4565 if ((ctxt == NULL) || (type == NULL)) {
4566 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4567 if (ctxt->error != NULL)
4568 ctxt->error(ctxt->userData,
4569 "Internal error: xmlSchemaValidateBasicType\n",
4570 node->name);
4571 return(-1);
4572 }
4573 /*
4574 * First check the content model of the node.
4575 */
4576 cur = child;
4577 while (cur != NULL) {
4578 switch (cur->type) {
4579 case XML_TEXT_NODE:
4580 case XML_CDATA_SECTION_NODE:
4581 case XML_PI_NODE:
4582 case XML_COMMENT_NODE:
4583 case XML_XINCLUDE_START:
4584 case XML_XINCLUDE_END:
4585 break;
4586 case XML_ENTITY_REF_NODE:
4587 case XML_ENTITY_NODE:
4588 TODO
4589 break;
4590 case XML_ELEMENT_NODE:
4591 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
4592 if (ctxt->error != NULL)
4593 ctxt->error(ctxt->userData,
4594 "Element %s: child %s should not be present\n",
4595 node->name, cur->name);
4596 return(ctxt->err);
4597 case XML_ATTRIBUTE_NODE:
4598 case XML_DOCUMENT_NODE:
4599 case XML_DOCUMENT_TYPE_NODE:
4600 case XML_DOCUMENT_FRAG_NODE:
4601 case XML_NOTATION_NODE:
4602 case XML_HTML_DOCUMENT_NODE:
4603 case XML_DTD_NODE:
4604 case XML_ELEMENT_DECL:
4605 case XML_ATTRIBUTE_DECL:
4606 case XML_ENTITY_DECL:
4607 case XML_NAMESPACE_DECL:
4608#ifdef LIBXML_DOCB_ENABLED
4609 case XML_DOCB_DOCUMENT_NODE:
4610#endif
4611 ctxt->err = XML_SCHEMAS_ERR_INVALIDELEM;
4612 if (ctxt->error != NULL)
4613 ctxt->error(ctxt->userData,
4614 "Element %s: node type %d unexpected here\n",
4615 node->name, cur->type);
4616 return(ctxt->err);
4617 }
4618 cur = cur->next;
4619 }
4620 if (child == NULL)
4621 value = NULL;
4622 else
4623 value = xmlNodeGetContent(child->parent);
4624
4625 if (ctxt->value != NULL) {
4626 xmlSchemaFreeValue(ctxt->value);
4627 ctxt->value = NULL;
4628 }
4629 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
4630 if (value != NULL)
4631 xmlFree(value);
4632 if (ret != 0) {
4633 ctxt->error(ctxt->userData,
4634 "Element %s: failed to validate basic type %s\n",
4635 node->name, type->name);
4636 }
4637 return(ret);
4638}
4639
4640/**
4641 * xmlSchemaValidateComplexType:
4642 * @ctxt: a schema validation context
4643 * @node: the top node.
4644 *
4645 * Validate the content of an element expected to be a complex type type
4646 * xmlschema-1.html#cvc-complex-type
4647 * Validation Rule: Element Locally Valid (Complex Type)
4648 *
4649 * Returns 0 if the element is schemas valid, a positive error code
4650 * number otherwise and -1 in case of internal or API error.
4651 */
4652static int
4653xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4654 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00004655 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004656 int ret;
4657
4658 child = ctxt->node;
4659 type = ctxt->type;
4660
Daniel Veillard4255d502002-04-16 15:50:10 +00004661 switch (type->contentType) {
4662 case XML_SCHEMA_CONTENT_EMPTY:
4663 if (child != NULL) {
4664 if (ctxt->error != NULL)
4665 ctxt->error(ctxt->userData,
4666 "Element %s is supposed to be empty\n",
4667 node->name);
4668 }
Daniel Veillarde19fc232002-04-22 16:01:24 +00004669 if (type->attributes != NULL) {
4670 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4671 }
4672 subtype = type->subtypes;
4673 while (subtype != NULL) {
4674 ctxt->type = subtype;
4675 xmlSchemaValidateComplexType(ctxt, node);
4676 subtype = subtype->next;
4677 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004678 break;
4679 case XML_SCHEMA_CONTENT_ELEMENTS:
4680 case XML_SCHEMA_CONTENT_MIXED:
4681 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4682 /*
4683 * Skip ignorable nodes in that context
4684 */
4685 child = xmlSchemaSkipIgnored(ctxt, type, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004686 while (child != NULL) {
4687 if (child->type == XML_ELEMENT_NODE) {
4688 ret = xmlRegExecPushString(ctxt->regexp,
4689 child->name, child);
4690#ifdef DEBUG_AUTOMATA
4691 if (ret < 0)
4692 xmlGenericError(xmlGenericErrorContext,
4693 " --> %s Error\n", child->name);
4694 else
4695 xmlGenericError(xmlGenericErrorContext,
4696 " --> %s\n", child->name);
4697#endif
4698 }
4699 child = child->next;
4700 /*
4701 * Skip ignorable nodes in that context
4702 */
4703 child = xmlSchemaSkipIgnored(ctxt, type, child);
4704 }
4705 break;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004706 case XML_SCHEMA_CONTENT_BASIC: {
4707 if (type->subtypes != NULL) {
4708 ctxt->type = type->subtypes;
4709 xmlSchemaValidateComplexType(ctxt, node);
4710 }
4711 if (type->baseType != NULL) {
4712 ctxt->type = type->baseType;
4713 xmlSchemaValidateBasicType(ctxt, node);
4714 }
4715 if (type->attributes != NULL) {
4716 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4717 }
4718 ctxt->type = type;
4719 break;
4720 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004721 default:
4722 TODO
4723 xmlGenericError(xmlGenericErrorContext,
4724 "unimplemented content type %d\n",
4725 type->contentType);
4726 }
4727 return(ctxt->err);
4728}
4729
4730/**
4731 * xmlSchemaValidateContent:
4732 * @ctxt: a schema validation context
4733 * @elem: an element
4734 * @type: the type declaration
4735 *
4736 * Validate the content of an element against the type.
4737 *
4738 * Returns 0 if the element is schemas valid, a positive error code
4739 * number otherwise and -1 in case of internal or API error.
4740 */
4741static int
4742xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
4743 xmlNodePtr child;
4744 xmlSchemaTypePtr type;
4745
4746 child = ctxt->node;
4747 type = ctxt->type;
4748
Daniel Veillarde19fc232002-04-22 16:01:24 +00004749 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4750
Daniel Veillard4255d502002-04-16 15:50:10 +00004751 switch (type->type) {
4752 case XML_SCHEMA_TYPE_ANY:
4753 /* Any type will do it, fine */
4754 TODO /* handle recursivity */
4755 break;
4756 case XML_SCHEMA_TYPE_COMPLEX:
4757 xmlSchemaValidateComplexType(ctxt, node);
4758 break;
4759 case XML_SCHEMA_TYPE_ELEMENT: {
4760 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
4761 /*
4762 * Handle element reference here
4763 */
4764 if (decl->ref != NULL) {
4765 if (decl->refDecl == NULL) {
4766 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4767 if (ctxt->error != NULL)
4768 ctxt->error(ctxt->userData,
4769 "Internal error: element reference %s not resolved\n",
4770 decl->ref);
4771 return(-1);
4772 }
4773 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
4774 decl = decl->refDecl;
4775 }
4776 xmlSchemaValidateElementType(ctxt, node);
4777 ctxt->type = type;
4778 break;
4779 }
4780 case XML_SCHEMA_TYPE_BASIC:
4781 xmlSchemaValidateBasicType(ctxt, node);
4782 break;
4783 case XML_SCHEMA_TYPE_FACET:
4784 TODO
4785 break;
4786 case XML_SCHEMA_TYPE_SIMPLE:
4787 xmlSchemaValidateSimpleType(ctxt, node);
4788 break;
4789 case XML_SCHEMA_TYPE_SEQUENCE:
4790 TODO
4791 break;
4792 case XML_SCHEMA_TYPE_CHOICE:
4793 TODO
4794 break;
4795 case XML_SCHEMA_TYPE_ALL:
4796 TODO
4797 break;
4798 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
4799 TODO
4800 break;
4801 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4802 TODO
4803 break;
4804 case XML_SCHEMA_TYPE_UR:
4805 TODO
4806 break;
4807 case XML_SCHEMA_TYPE_RESTRICTION:
4808 /*xmlSchemaValidateRestrictionType(ctxt, node); */
4809 TODO
4810 break;
4811 case XML_SCHEMA_TYPE_EXTENSION:
4812 TODO
4813 break;
4814 case XML_SCHEMA_TYPE_ATTRIBUTE:
4815 TODO
4816 break;
4817 case XML_SCHEMA_TYPE_GROUP:
4818 TODO
4819 break;
4820 case XML_SCHEMA_TYPE_NOTATION:
4821 TODO
4822 break;
4823 case XML_SCHEMA_TYPE_LIST:
4824 TODO
4825 break;
4826 case XML_SCHEMA_TYPE_UNION:
4827 TODO
4828 break;
4829 case XML_SCHEMA_FACET_MININCLUSIVE:
4830 TODO
4831 break;
4832 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4833 TODO
4834 break;
4835 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4836 TODO
4837 break;
4838 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4839 TODO
4840 break;
4841 case XML_SCHEMA_FACET_TOTALDIGITS:
4842 TODO
4843 break;
4844 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4845 TODO
4846 break;
4847 case XML_SCHEMA_FACET_PATTERN:
4848 TODO
4849 break;
4850 case XML_SCHEMA_FACET_ENUMERATION:
4851 TODO
4852 break;
4853 case XML_SCHEMA_FACET_WHITESPACE:
4854 TODO
4855 break;
4856 case XML_SCHEMA_FACET_LENGTH:
4857 TODO
4858 break;
4859 case XML_SCHEMA_FACET_MAXLENGTH:
4860 TODO
4861 break;
4862 case XML_SCHEMA_FACET_MINLENGTH:
4863 TODO
4864 break;
4865 }
4866 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
4867
4868 if (ctxt->node == NULL)
4869 return(ctxt->err);
4870 ctxt->node = ctxt->node->next;
4871 ctxt->type = type->next;
4872 return(ctxt->err);
4873}
4874
4875/**
4876 * xmlSchemaValidateType:
4877 * @ctxt: a schema validation context
4878 * @elem: an element
4879 * @type: the list of type declarations
4880 *
4881 * Validate the content of an element against the types.
4882 *
4883 * Returns 0 if the element is schemas valid, a positive error code
4884 * number otherwise and -1 in case of internal or API error.
4885 */
4886static int
4887xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
4888 xmlSchemaElementPtr elemDecl,
4889 xmlSchemaTypePtr type) {
4890 xmlChar *nil;
4891
4892 if ((elem->content == NULL) || (type == NULL) || (elemDecl == NULL))
4893 return(0);
4894 /*
4895 * 3.3.4 : 2
4896 */
4897 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
4898 ctxt->err = XML_SCHEMAS_ERR_ISABSTRACT;
4899 if (ctxt->error != NULL)
4900 ctxt->error(ctxt->userData, "Element %s is abstract\n", elem->name);
4901 return(ctxt->err);
4902 }
4903 /*
4904 * 3.3.4: 3
4905 */
4906 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
4907 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
4908 /* 3.3.4: 3.2 */
4909 if (xmlStrEqual(nil, BAD_CAST "true")) {
4910 if (elem->children != NULL) {
4911 ctxt->err = XML_SCHEMAS_ERR_NOTEMPTY;
4912 if (ctxt->error != NULL)
4913 ctxt->error(ctxt->userData, "Element %s is not empty\n",
4914 elem->name);
4915 return(ctxt->err);
4916 }
4917 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
4918 (elemDecl->value != NULL)) {
4919 ctxt->err = XML_SCHEMAS_ERR_HAVEDEFAULT;
4920 if (ctxt->error != NULL)
4921 ctxt->error(ctxt->userData,
4922 "Empty element %s cannot get a fixed value\n",
4923 elem->name);
4924 return(ctxt->err);
4925 }
4926 }
4927 } else {
4928 /* 3.3.4: 3.1 */
4929 if (nil != NULL) {
4930 ctxt->err = XML_SCHEMAS_ERR_NOTNILLABLE;
4931 if (ctxt->error != NULL)
4932 ctxt->error(ctxt->userData,
4933 "Element %s with xs:nil but not nillable\n",
4934 elem->name);
4935 xmlFree(nil);
4936 return(ctxt->err);
4937 }
4938 }
4939
4940 /* TODO 3.3.4: 4 if the element carries xs:type*/
4941
4942 ctxt->type = elemDecl->subtypes;
4943 ctxt->node = elem->children;
4944 xmlSchemaValidateContent(ctxt, elem);
4945 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
4946
4947 return(ctxt->err);
4948}
4949
4950
4951/**
4952 * xmlSchemaValidateAttributes:
4953 * @ctxt: a schema validation context
4954 * @elem: an element
4955 * @attributes: the list of attribute declarations
4956 *
4957 * Validate the attributes of an element.
4958 *
4959 * Returns 0 if the element is schemas valid, a positive error code
4960 * number otherwise and -1 in case of internal or API error.
4961 */
4962static int
4963xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
4964 xmlSchemaAttributePtr attributes) {
4965 int i, ret;
4966 xmlAttrPtr attr;
4967 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004968 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004969
4970 if (attributes == NULL)
4971 return(0);
4972 while (attributes != NULL) {
Daniel Veillard13e04c62002-04-23 17:51:29 +00004973 /*
4974 * Handle attribute groups
4975 */
4976 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
4977 group = (xmlSchemaAttributeGroupPtr) attributes;
4978 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
4979 attributes = group->next;
4980 continue;
4981 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004982 for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
4983 attr = ctxt->attr[i].attr;
4984 if (attr == NULL)
4985 continue;
4986 if (!xmlStrEqual(attr->name, attributes->name))
4987 continue;
4988 /*
4989 * TODO: handle the mess about namespaces here.
4990 */
4991 if ((attr->ns != NULL) /* || (attributes->ns != NULL) */) {
4992 TODO
4993 }
4994 if (attributes->subtypes == NULL) {
4995 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
4996 if (ctxt->error != NULL)
4997 ctxt->error(ctxt->userData,
4998 "Internal error: attribute %s type not resolved\n",
4999 attr->name);
5000 continue;
5001 }
5002 value = xmlNodeListGetString(elem->doc, attr->children, 1);
5003 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
Daniel Veillard13e04c62002-04-23 17:51:29 +00005004 value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005005 if (ret != 0) {
5006 ctxt->err = XML_SCHEMAS_ERR_ATTRINVALID;
5007 if (ctxt->error != NULL)
5008 ctxt->error(ctxt->userData,
5009 "attribute %s on %s does not match type\n",
5010 attr->name, elem->name);
5011 } else {
5012 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
5013 }
5014 if (value != NULL) {
5015 xmlFree(value);
5016 }
5017 }
5018 attributes = attributes->next;
5019 }
5020 return(ctxt->err);
5021}
5022
5023/**
5024 * xmlSchemaValidateElement:
5025 * @ctxt: a schema validation context
5026 * @elem: an element
5027 *
5028 * Validate an element in a tree
5029 *
5030 * Returns 0 if the element is schemas valid, a positive error code
5031 * number otherwise and -1 in case of internal or API error.
5032 */
5033static int
5034xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem) {
5035 xmlSchemaElementPtr elemDecl;
5036 int ret, attrBase;
5037
5038 if (elem->ns != NULL)
5039 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5040 elem->name, elem->ns->href, NULL);
5041 else
5042 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5043 elem->name, NULL, NULL);
5044 /*
5045 * 3.3.4 : 1
5046 */
5047 if (elemDecl == NULL) {
5048 ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
5049 if (ctxt->error != NULL)
5050 ctxt->error(ctxt->userData, "Element %s not declared\n",
5051 elem->name);
5052 return(ctxt->err);
5053 }
5054 if (elemDecl->subtypes == NULL) {
5055 ctxt->err = XML_SCHEMAS_ERR_NOTYPE;
5056 if (ctxt->error != NULL)
5057 ctxt->error(ctxt->userData, "Element %s has no type\n",
5058 elem->name);
5059 return(ctxt->err);
5060 }
5061 /*
5062 * Verify the attributes
5063 */
5064 attrBase = ctxt->attrBase;
5065 ctxt->attrBase = ctxt->attrNr;
5066 xmlSchemaRegisterAttributes(ctxt, elem->properties);
5067 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
5068 /*
5069 * Verify the element content recursively
5070 */
5071 if (elemDecl->contModel != NULL) {
5072 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
5073 (xmlRegExecCallbacks) xmlSchemaValidateCallback,
5074 ctxt);
5075#ifdef DEBUG_AUTOMATA
5076 xmlGenericError(xmlGenericErrorContext,
5077 "====> %s\n", elem->name);
5078#endif
5079 }
5080 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005081 if (elemDecl->contModel != NULL) {
5082 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005083#ifdef DEBUG_AUTOMATA
Daniel Veillard4255d502002-04-16 15:50:10 +00005084 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005085 "====> %s : %d\n", elem->name, ret);
5086#endif
5087 if (ret == 0) {
5088 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
5089 if (ctxt->error != NULL)
5090 ctxt->error(ctxt->userData, "Element %s content check failed\n",
5091 elem->name);
5092 } else if (ret < 0) {
5093 ctxt->err = XML_SCHEMAS_ERR_ELEMCONT;
5094 if (ctxt->error != NULL)
5095 ctxt->error(ctxt->userData, "Element %s content check failed\n",
5096 elem->name);
5097#ifdef DEBUG_CONTENT
5098 } else {
5099 xmlGenericError(xmlGenericErrorContext,
5100 "Element %s content check succeeded\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005101
5102#endif
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005103 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005104 xmlRegFreeExecCtxt(ctxt->regexp);
5105 }
5106 /*
5107 * Verify that all attributes were Schemas-validated
5108 */
5109 xmlSchemaCheckAttributes(ctxt, elem);
5110 ctxt->attrNr = ctxt->attrBase;
5111 ctxt->attrBase = attrBase;
5112
5113 return(ctxt->err);
5114}
5115
5116/**
5117 * xmlSchemaValidateDocument:
5118 * @ctxt: a schema validation context
5119 * @doc: a parsed document tree
5120 *
5121 * Validate a document tree in memory.
5122 *
5123 * Returns 0 if the document is schemas valid, a positive error code
5124 * number otherwise and -1 in case of internal or API error.
5125 */
5126static int
5127xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5128 xmlNodePtr root;
5129 xmlSchemaElementPtr elemDecl;
5130
5131 root = xmlDocGetRootElement(doc);
5132 if (root == NULL) {
5133 ctxt->err = XML_SCHEMAS_ERR_NOROOT;
5134 if (ctxt->error != NULL)
5135 ctxt->error(ctxt->userData, "document has no root\n");
5136 return(ctxt->err);
5137 }
5138 if (root->ns != NULL)
5139 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5140 root->name, root->ns->href, NULL);
5141 else
5142 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
5143 root->name, NULL, NULL);
5144 if (elemDecl == NULL) {
5145 ctxt->err = XML_SCHEMAS_ERR_UNDECLAREDELEM;
5146 if (ctxt->error != NULL)
5147 ctxt->error(ctxt->userData, "Element %s not declared\n",
5148 root->name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005149 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005150 ctxt->err = XML_SCHEMAS_ERR_NOTTOPLEVEL;
5151 if (ctxt->error != NULL)
5152 ctxt->error(ctxt->userData, "Root element %s not toplevel\n",
5153 root->name);
5154 }
5155 /*
5156 * Okay, start the recursive validation
5157 */
5158 xmlSchemaValidateElement(ctxt, root);
5159
5160 return(ctxt->err);
5161}
5162
5163/************************************************************************
5164 * *
5165 * SAX Validation code *
5166 * *
5167 ************************************************************************/
5168
5169/************************************************************************
5170 * *
5171 * Validation interfaces *
5172 * *
5173 ************************************************************************/
5174
5175/**
5176 * xmlSchemaNewValidCtxt:
5177 * @schema: a precompiled XML Schemas
5178 *
5179 * Create an XML Schemas validation context based on the given schema
5180 *
5181 * Returns the validation context or NULL in case of error
5182 */
5183xmlSchemaValidCtxtPtr
5184xmlSchemaNewValidCtxt(xmlSchemaPtr schema) {
5185 xmlSchemaValidCtxtPtr ret;
5186
5187 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
5188 if (ret == NULL) {
5189 xmlGenericError(xmlGenericErrorContext,
5190 "Failed to allocate new schama validation context\n");
5191 return (NULL);
5192 }
5193 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
5194 ret->schema = schema;
5195 ret->attrNr = 0;
5196 ret->attrMax = 10;
5197 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
5198 sizeof(xmlSchemaAttrState));
5199 if (ret->attr == NULL) {
5200 free(ret);
5201 return(NULL);
5202 }
5203 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
5204 return (ret);
5205}
5206
5207/**
5208 * xmlSchemaFreeValidCtxt:
5209 * @ctxt: the schema validation context
5210 *
5211 * Free the resources associated to the schema validation context
5212 */
5213void
5214xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) {
5215 if (ctxt == NULL)
5216 return;
5217 if (ctxt->attr != NULL)
5218 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00005219 if (ctxt->value != NULL)
5220 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005221 xmlFree(ctxt);
5222}
5223
5224/**
5225 * xmlSchemaSetValidErrors:
5226 * @ctxt: a schema validation context
5227 * @err: the error function
5228 * @warn: the warning function
5229 * @ctxt: the functions context
5230 *
5231 * Set the error and warning callback informations
5232 */
5233void
5234xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
5235 xmlSchemaValidityErrorFunc err,
5236 xmlSchemaValidityWarningFunc warn, void *ctx) {
5237 if (ctxt == NULL)
5238 return;
5239 ctxt->error = err;
5240 ctxt->warning = warn;
5241 ctxt->userData = ctx;
5242}
5243
5244/**
5245 * xmlSchemaValidateDoc:
5246 * @ctxt: a schema validation context
5247 * @doc: a parsed document tree
5248 *
5249 * Validate a document tree in memory.
5250 *
5251 * Returns 0 if the document is schemas valid, a positive error code
5252 * number otherwise and -1 in case of internal or API error.
5253 */
5254int
5255xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) {
5256 int ret;
5257
5258 if ((ctxt == NULL) || (doc == NULL))
5259 return(-1);
5260
5261 ctxt->doc = doc;
5262 ret = xmlSchemaValidateDocument(ctxt, doc);
5263 return(ret);
5264}
5265
5266/**
5267 * xmlSchemaValidateStream:
5268 * @ctxt: a schema validation context
5269 * @input: the input to use for reading the data
5270 * @enc: an optional encoding information
5271 * @sax: a SAX handler for the resulting events
5272 * @user_data: the context to provide to the SAX handler.
5273 *
5274 * Validate a document tree in memory.
5275 *
5276 * Returns 0 if the document is schemas valid, a positive error code
5277 * number otherwise and -1 in case of internal or API error.
5278 */
5279int
5280xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
5281 xmlParserInputBufferPtr input, xmlCharEncoding enc,
5282 xmlSAXHandlerPtr sax, void *user_data) {
5283 if ((ctxt == NULL) || (input == NULL))
5284 return(-1);
5285 ctxt->input = input;
5286 ctxt->enc = enc;
5287 ctxt->sax = sax;
5288 ctxt->user_data = user_data;
5289 TODO
5290 return(0);
5291}
5292
5293#endif /* LIBXML_SCHEMAS_ENABLED */