1 /*
2 * libxml2_xmlschemas.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 * Portion Copyright � 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
9 */
10
11 /*
12
13
14
15
16 */
17 #define IN_LIBXML
18 #include "xmlenglibxml.h"
19
20 #if defined(LIBXML_SCHEMAS_ENABLED) || defined(XMLENGINE_XMLSCHEMA_DATATYPES)
21
22
23 #include <string.h>
24 #include <libxml2_globals.h>
25 #include <libxml2_parser.h>
26 #include <libxml2_parserinternals.h>
27 #include "libxml2_xmlerror2.h"
28 #include <libxml2_hash.h>
29 #include <libxml2_uri.h>
30 #include "libxml2_xmlschemas.h"
31 #include <libxml2_schemasinternals.h>
32 #include "libxml2_xmlschemastypes.h"
33
34 #ifdef LIBXML_AUTOMATA_ENABLED
35 #include "libxml2_xmlautomata.h"
36 #endif
37
38 #ifdef LIBXML_REGEXP_ENABLED
39 #include "libxml2_xmlregexp.h"
40 #endif
41
42 #include <libxml2_dict.h>
43
44 /* #define DEBUG 1 */
45
46 /* #define DEBUG_CONTENT 1 */
47
48 /* #define DEBUG_TYPE 1 */
49
50 /* #define DEBUG_CONTENT_REGEXP 1 */
51
52 /* #define DEBUG_AUTOMATA 1 */
53
54 #define UNBOUNDED (1 << 30)
55 #define TODO \
56 xmlGenericError(xmlGenericErrorContext, \
57 "Unimplemented block at %s:%d\n", \
58 __FILE__, __LINE__);
59
60 #define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar*)"the default namespace"
61
62 /*
63 * The XML Schemas namespaces
64 */
65 static const xmlChar* const xmlSchemaNs = (const xmlChar*)
66 "http://www.w3.org/2001/XMLSchema";
67
68 static const xmlChar* const xmlSchemaInstanceNs = (const xmlChar*)
69 "http://www.w3.org/2001/XMLSchema-instance";
70
71 /**
72 * xmlSchemaFreeAnnot:
73 * @param annot a schema type structure
74 *
75 * Deallocate a annotation structure
76 */
77 static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)78 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
79 {
80 if (annot == NULL)
81 return;
82 xmlFree(annot);
83 }
84
85 /**
86 * xmlSchemaFreeType:
87 * @param type a schema type structure
88 *
89 * Deallocate a Schema Type structure.
90 */
91 XMLPUBFUNEXPORT void
xmlSchemaFreeType(xmlSchemaTypePtr type)92 xmlSchemaFreeType(xmlSchemaTypePtr type)
93 {
94 if (type == NULL)
95 return;
96 if (type->annot != NULL)
97 xmlSchemaFreeAnnot(type->annot);
98 if (type->facets != NULL) {
99 xmlSchemaFacetPtr facet, next;
100
101 facet = type->facets;
102 while (facet != NULL) {
103 next = facet->next;
104 xmlSchemaFreeFacet(facet);
105 facet = next;
106 }
107 }
108 xmlFree(type);
109 }
110
111
112 /**
113 * xmlSchemaFreeFacet:
114 * @param facet a schema facet structure
115 *
116 * Deallocate a Schema Facet structure.
117 */
118 XMLPUBFUNEXPORT void
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)119 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
120 {
121 if (facet == NULL)
122 return;
123 if (facet->val != NULL)
124 xmlSchemaFreeValue(facet->val);
125 #ifdef LIBXML_REGEXP_ENABLED
126 if (facet->regexp != NULL)
127 xmlRegFreeRegexp(facet->regexp);
128 #endif
129 if (facet->annot != NULL)
130 xmlSchemaFreeAnnot(facet->annot);
131 xmlFree(facet);
132 }
133
134 #endif /* defined(LIBXML_SCHEMAS_ENABLED) || defined(XMLENGINE_XMLSCHEMA_DATATYPES) */
135
136 #ifdef LIBXML_SCHEMAS_ENABLED
137
138 #define IS_SCHEMA(node, type) \
139 ((node != NULL) && (node->ns != NULL) && \
140 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
141 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
142
143 #define XML_SCHEMAS_PARSE_ERROR 1
144
145 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
146
147 struct _xmlSchemaParserCtxt {
148 void *userData; /* user specific data block */
149 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
150 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
151 xmlSchemaValidError err;
152 int nberrors;
153 xmlStructuredErrorFunc serror;
154
155 xmlSchemaPtr topschema; /* The main schema */
156 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
157
158 xmlSchemaPtr schema; /* The schema in use */
159 const xmlChar *container; /* the current element, group, ... */
160 int counter;
161
162 const xmlChar *URL;
163 xmlDocPtr doc;
164 int preserve; /* Whether the doc should be freed */
165
166 const char *buffer;
167 int size;
168
169 /*
170 * Used to build complex element content models
171 */
172 xmlAutomataPtr am;
173 xmlAutomataStatePtr start;
174 xmlAutomataStatePtr end;
175 xmlAutomataStatePtr state;
176
177 xmlDictPtr dict; /* dictionnary for interned string names */
178 int includes; /* the inclusion level, 0 for root or imports */
179 };
180
181
182 #define XML_SCHEMAS_ATTR_UNKNOWN 1
183 #define XML_SCHEMAS_ATTR_CHECKED 2
184
185 typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
186 typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
187 struct _xmlSchemaAttrState {
188 xmlAttrPtr attr;
189 int state;
190 };
191
192 /**
193 * xmlSchemaValidCtxt:
194 *
195 * A Schemas validation context
196 */
197
198 struct _xmlSchemaValidCtxt {
199 void *userData; /* user specific data block */
200 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
201 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
202 xmlStructuredErrorFunc serror;
203
204 xmlSchemaPtr schema; /* The schema in use */
205 xmlDocPtr doc;
206 xmlParserInputBufferPtr input;
207 xmlCharEncoding enc;
208 xmlSAXHandlerPtr sax;
209 void *user_data;
210
211 xmlDocPtr myDoc;
212 int err;
213 int nberrors;
214
215 xmlNodePtr node;
216 xmlNodePtr cur;
217 xmlSchemaTypePtr type;
218
219 xmlRegExecCtxtPtr regexp;
220 xmlSchemaValPtr value;
221
222 int attrNr;
223 int attrBase;
224 int attrMax;
225 xmlSchemaAttrStatePtr attr;
226 };
227
228 /*
229 * These are the entries in the schemas importSchemas hash table
230 */
231 typedef struct _xmlSchemaImport xmlSchemaImport;
232 typedef xmlSchemaImport *xmlSchemaImportPtr;
233 struct _xmlSchemaImport {
234 const xmlChar *schemaLocation;
235 xmlSchemaPtr schema;
236 };
237
238 /*
239 * These are the entries associated to includes in a schemas
240 */
241 typedef struct _xmlSchemaInclude xmlSchemaInclude;
242 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
243 struct _xmlSchemaInclude {
244 xmlSchemaIncludePtr next;
245
246 const xmlChar *schemaLocation;
247 xmlDocPtr doc;
248 };
249
250
251
252 /************************************************************************
253 * *
254 * Some predeclarations *
255 * *
256 ************************************************************************/
257 static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
258 xmlSchemaTypePtr type,
259 const xmlChar * value);
260
261 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
262 xmlSchemaPtr schema,
263 xmlNodePtr node);
264 static int
265 xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
266 xmlSchemaTypePtr type,
267 const xmlChar * value,
268 int fireErrors);
269
270 /************************************************************************
271 * *
272 * Datatype error handlers *
273 * *
274 ************************************************************************/
275
276 /**
277 * xmlSchemaPErrMemory:
278 * @param node a context node
279 * @param extra extra informations
280 *
281 * Handle an out of memory condition
282 */
283 static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,const char * extra,xmlNodePtr node)284 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
285 const char *extra, xmlNodePtr node)
286 {
287 if (ctxt != NULL)
288 ctxt->nberrors++;
289 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
290 extra);
291 }
292
293 /**
294 * xmlSchemaPErr:
295 * @param ctxt the parsing context
296 * @param node the context node
297 * @param error the error code
298 * @param msg the error message
299 * @param str1 extra data
300 * @param str2 extra data
301 *
302 * Handle a parser error
303 */
304 static void
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)305 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
306 const char *msg, const xmlChar * str1, const xmlChar * str2)
307 {
308 xmlGenericErrorFunc channel = NULL;
309 xmlStructuredErrorFunc schannel = NULL;
310 void *data = NULL;
311
312 if (ctxt != NULL) {
313 ctxt->nberrors++;
314 channel = ctxt->error;
315 data = ctxt->userData;
316 schannel = ctxt->serror;
317 }
318 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
319 error, XML_ERR_ERROR, NULL, 0,
320 (const char *) str1, (const char *) str2, NULL, 0, 0,
321 msg, str1, str2);
322 }
323
324 /**
325 * xmlSchemaPErr2:
326 * @param ctxt the parsing context
327 * @param node the context node
328 * @param node the current child
329 * @param error the error code
330 * @param msg the error message
331 * @param str1 extra data
332 * @param str2 extra data
333 *
334 * Handle a parser error
335 */
336 static void
xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,xmlNodePtr child,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)337 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
338 xmlNodePtr child, int error,
339 const char *msg, const xmlChar * str1, const xmlChar * str2)
340 {
341 if (child != NULL)
342 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
343 else
344 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
345 }
346
347 /**
348 * xmlSchemaVTypeErrMemory:
349 * @param node a context node
350 * @param extra extra informations
351 *
352 * Handle an out of memory condition
353 */
354 static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,const char * extra,xmlNodePtr node)355 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
356 const char *extra, xmlNodePtr node)
357 {
358 if (ctxt != NULL) {
359 ctxt->nberrors++;
360 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
361 }
362 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
363 extra);
364 }
365
366 /**
367 * xmlSchemaVErr3:
368 * @param ctxt the validation context
369 * @param node the context node
370 * @param error the error code
371 * @param msg the error message
372 * @param str1 extra data
373 * @param str2 extra data
374 * @param str3 extra data
375 *
376 * Handle a validation error
377 */
378 static void
xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)379 xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
380 const char *msg, const xmlChar *str1, const xmlChar *str2,
381 const xmlChar *str3)
382 {
383 xmlStructuredErrorFunc schannel = NULL;
384 xmlGenericErrorFunc channel = NULL;
385 void *data = NULL;
386
387 if (ctxt != NULL) {
388 ctxt->nberrors++;
389 ctxt->err = error;
390 channel = ctxt->error;
391 schannel = ctxt->serror;
392 data = ctxt->userData;
393 }
394 /* reajust to global error numbers */
395 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
396 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
397 error, XML_ERR_ERROR, NULL, 0,
398 (const char *) str1, (const char *) str2,
399 (const char *) str3, 0, 0,
400 msg, str1, str2, str3);
401 }
402 /**
403 * xmlSchemaVErr:
404 * @param ctxt the validation context
405 * @param node the context node
406 * @param error the error code
407 * @param msg the error message
408 * @param str1 extra data
409 * @param str2 extra data
410 *
411 * Handle a validation error
412 */
413 static void
xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)414 xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
415 const char *msg, const xmlChar * str1, const xmlChar * str2)
416 {
417 xmlStructuredErrorFunc schannel = NULL;
418 xmlGenericErrorFunc channel = NULL;
419 void *data = NULL;
420
421 if (ctxt != NULL) {
422 ctxt->nberrors++;
423 ctxt->err = error;
424 channel = ctxt->error;
425 data = ctxt->userData;
426 schannel = ctxt->serror;
427 }
428 /* reajust to global error numbers */
429 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
430 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
431 error, XML_ERR_ERROR, NULL, 0,
432 (const char *) str1, (const char *) str2, NULL, 0, 0,
433 msg, str1, str2);
434 }
435
436 /************************************************************************
437 * *
438 * Allocation functions *
439 * *
440 ************************************************************************/
441
442 /**
443 * xmlSchemaNewSchema:
444 * @param ctxt a schema validation context
445 *
446 * Allocate a new Schema structure.
447 *
448 * Returns the newly allocated structure or NULL in case or error
449 */
450 static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)451 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
452 {
453 xmlSchemaPtr ret;
454
455 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
456 if (ret == NULL) {
457 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
458 return (NULL);
459 }
460 memset(ret, 0, sizeof(xmlSchema));
461 ret->dict = ctxt->dict;
462 xmlDictReference(ret->dict);
463
464 return (ret);
465 }
466
467 /**
468 * xmlSchemaNewFacet:
469 *
470 * Allocate a new Facet structure.
471 *
472 * Returns the newly allocated structure or NULL in case or error
473 */
474 xmlSchemaFacetPtr
xmlSchemaNewFacet(void)475 xmlSchemaNewFacet(void)
476 {
477 xmlSchemaFacetPtr ret;
478
479 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
480 if (ret == NULL) {
481 return (NULL);
482 }
483 memset(ret, 0, sizeof(xmlSchemaFacet));
484
485 return (ret);
486 }
487
488 /**
489 * xmlSchemaNewAnnot:
490 * @param ctxt a schema validation context
491 * @param node a node
492 *
493 * Allocate a new annotation structure.
494 *
495 * Returns the newly allocated structure or NULL in case or error
496 */
497 static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)498 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
499 {
500 xmlSchemaAnnotPtr ret;
501
502 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
503 if (ret == NULL) {
504 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
505 return (NULL);
506 }
507 memset(ret, 0, sizeof(xmlSchemaAnnot));
508 ret->content = node;
509 return (ret);
510 }
511
512
513
514 /**
515 * xmlSchemaFreeImport:
516 * @param import a schema import structure
517 *
518 * Deallocate an import structure
519 */
520 static void
xmlSchemaFreeImport(xmlSchemaImportPtr import)521 xmlSchemaFreeImport(xmlSchemaImportPtr import)
522 {
523 if (import == NULL)
524 return;
525
526 xmlSchemaFree(import->schema);
527 xmlFree(import);
528 }
529
530 /**
531 * xmlSchemaFreeInclude:
532 * @param include a schema include structure
533 *
534 * Deallocate an include structure
535 */
536 static void
xmlSchemaFreeInclude(xmlSchemaIncludePtr include)537 xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
538 {
539 if (include == NULL)
540 return;
541
542 xmlFreeDoc(include->doc);
543 xmlFree(include);
544 }
545
546 /**
547 * xmlSchemaFreeIncludeList:
548 * @param includes a schema include list
549 *
550 * Deallocate an include structure
551 */
552 static void
xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)553 xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
554 {
555 xmlSchemaIncludePtr next;
556
557 while (includes != NULL) {
558 next = includes->next;
559 xmlSchemaFreeInclude(includes);
560 includes = next;
561 }
562 }
563
564 /**
565 * xmlSchemaFreeNotation:
566 * @param schema a schema notation structure
567 *
568 * Deallocate a Schema Notation structure.
569 */
570 static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)571 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
572 {
573 if (nota == NULL)
574 return;
575 xmlFree(nota);
576 }
577
578 /**
579 * xmlSchemaFreeAttribute:
580 * @param schema a schema attribute structure
581 *
582 * Deallocate a Schema Attribute structure.
583 */
584 static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)585 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
586 {
587 if (attr == NULL)
588 return;
589 xmlFree(attr);
590 }
591
592 /**
593 * xmlSchemaFreeAttributeGroup:
594 * @param schema a schema attribute group structure
595 *
596 * Deallocate a Schema Attribute Group structure.
597 */
598 static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)599 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
600 {
601 if (attr == NULL)
602 return;
603 xmlFree(attr);
604 }
605
606 /**
607 * xmlSchemaFreeElement:
608 * @param schema a schema element structure
609 *
610 * Deallocate a Schema Element structure.
611 */
612 static void
xmlSchemaFreeElement(xmlSchemaElementPtr elem)613 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
614 {
615 if (elem == NULL)
616 return;
617 if (elem->annot != NULL)
618 xmlSchemaFreeAnnot(elem->annot);
619 if (elem->contModel != NULL)
620 xmlRegFreeRegexp(elem->contModel);
621 xmlFree(elem);
622 }
623
624 /**
625 * xmlSchemaFreeTypeList:
626 * @param type a schema type structure
627 *
628 * Deallocate a Schema Type structure.
629 */
630 static void
xmlSchemaFreeTypeList(xmlSchemaTypePtr type)631 xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
632 {
633 xmlSchemaTypePtr next;
634
635 while (type != NULL) {
636 next = type->redef;
637 xmlSchemaFreeType(type);
638 type = next;
639 }
640 }
641
642 /**
643 * xmlSchemaFree:
644 * @param schema a schema structure
645 *
646 * Deallocate a Schema structure.
647 */
648 void
xmlSchemaFree(xmlSchemaPtr schema)649 xmlSchemaFree(xmlSchemaPtr schema)
650 {
651 if (schema == NULL)
652 return;
653
654 if (schema->notaDecl != NULL)
655 xmlHashFree(schema->notaDecl,
656 (xmlHashDeallocator) xmlSchemaFreeNotation);
657 if (schema->attrDecl != NULL)
658 xmlHashFree(schema->attrDecl,
659 (xmlHashDeallocator) xmlSchemaFreeAttribute);
660 if (schema->attrgrpDecl != NULL)
661 xmlHashFree(schema->attrgrpDecl,
662 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
663 if (schema->elemDecl != NULL)
664 xmlHashFree(schema->elemDecl,
665 (xmlHashDeallocator) xmlSchemaFreeElement);
666 if (schema->typeDecl != NULL)
667 xmlHashFree(schema->typeDecl,
668 (xmlHashDeallocator) xmlSchemaFreeTypeList);
669 if (schema->groupDecl != NULL)
670 xmlHashFree(schema->groupDecl,
671 (xmlHashDeallocator) xmlSchemaFreeType);
672 if (schema->schemasImports != NULL)
673 xmlHashFree(schema->schemasImports,
674 (xmlHashDeallocator) xmlSchemaFreeImport);
675 if (schema->includes != NULL) {
676 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
677 }
678 if (schema->annot != NULL)
679 xmlSchemaFreeAnnot(schema->annot);
680 if (schema->doc != NULL && !schema->preserve)
681 xmlFreeDoc(schema->doc);
682 xmlDictFree(schema->dict);
683
684 xmlFree(schema);
685 }
686
687 /************************************************************************
688 * *
689 * Debug functions *
690 * *
691 ************************************************************************/
692
693 #ifdef LIBXML_OUTPUT_ENABLED
694
695 /**
696 * xmlSchemaElementDump:
697 * @param elem an element
698 * @param output the file output
699 *
700 * Dump the element
701 */
702 static void
xmlSchemaElementDump(xmlSchemaElementPtr elem,FILE * output,const xmlChar * name ATTRIBUTE_UNUSED,const xmlChar * context ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED)703 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
704 const xmlChar * name ATTRIBUTE_UNUSED,
705 const xmlChar * context ATTRIBUTE_UNUSED,
706 const xmlChar * namespace ATTRIBUTE_UNUSED)
707 {
708 if (elem == NULL)
709 return;
710
711 fprintf(output, "Element ");
712 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
713 fprintf(output, "toplevel ");
714 fprintf(output, ": %s ", elem->name);
715 if (namespace != NULL)
716 fprintf(output, "namespace '%s' ", namespace);
717
718 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
719 fprintf(output, "nillable ");
720 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
721 fprintf(output, "global ");
722 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
723 fprintf(output, "default ");
724 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
725 fprintf(output, "fixed ");
726 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
727 fprintf(output, "abstract ");
728 if (elem->flags & XML_SCHEMAS_ELEM_REF)
729 fprintf(output, "ref '%s' ", elem->ref);
730 if (elem->id != NULL)
731 fprintf(output, "id '%s' ", elem->id);
732 fprintf(output, "\n");
733 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
734 fprintf(output, " ");
735 if (elem->minOccurs != 1)
736 fprintf(output, "min: %d ", elem->minOccurs);
737 if (elem->maxOccurs >= UNBOUNDED)
738 fprintf(output, "max: unbounded\n");
739 else if (elem->maxOccurs != 1)
740 fprintf(output, "max: %d\n", elem->maxOccurs);
741 else
742 fprintf(output, "\n");
743 }
744 if (elem->namedType != NULL) {
745 fprintf(output, " type: %s", elem->namedType);
746 if (elem->namedTypeNs != NULL)
747 fprintf(output, " ns %s\n", elem->namedTypeNs);
748 else
749 fprintf(output, "\n");
750 }
751 if (elem->substGroup != NULL) {
752 fprintf(output, " substitutionGroup: %s", elem->substGroup);
753 if (elem->substGroupNs != NULL)
754 fprintf(output, " ns %s\n", elem->substGroupNs);
755 else
756 fprintf(output, "\n");
757 }
758 if (elem->value != NULL)
759 fprintf(output, " default: %s", elem->value);
760 }
761
762 /**
763 * xmlSchemaAnnotDump:
764 * @param output the file output
765 * @param annot a annotation
766 *
767 * Dump the annotation
768 */
769 static void
xmlSchemaAnnotDump(FILE * output,xmlSchemaAnnotPtr annot)770 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
771 {
772 xmlChar *content;
773
774 if (annot == NULL)
775 return;
776
777 content = xmlNodeGetContent(annot->content);
778 if (content != NULL) {
779 fprintf(output, " Annot: %s\n", content);
780 xmlFree(content);
781 } else
782 fprintf(output, " Annot: empty\n");
783 }
784
785 /**
786 * xmlSchemaTypeDump:
787 * @param output the file output
788 * @param type a type structure
789 *
790 * Dump a SchemaType structure
791 */
792 static void
xmlSchemaTypeDump(xmlSchemaTypePtr type,FILE * output)793 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
794 {
795 if (type == NULL) {
796 fprintf(output, "Type: NULL\n");
797 return;
798 }
799 fprintf(output, "Type: ");
800 if (type->name != NULL)
801 fprintf(output, "%s, ", type->name);
802 else
803 fprintf(output, "no name");
804 switch (type->type) {
805 case XML_SCHEMA_TYPE_BASIC:
806 fprintf(output, "basic ");
807 break;
808 case XML_SCHEMA_TYPE_SIMPLE:
809 fprintf(output, "simple ");
810 break;
811 case XML_SCHEMA_TYPE_COMPLEX:
812 fprintf(output, "complex ");
813 break;
814 case XML_SCHEMA_TYPE_SEQUENCE:
815 fprintf(output, "sequence ");
816 break;
817 case XML_SCHEMA_TYPE_CHOICE:
818 fprintf(output, "choice ");
819 break;
820 case XML_SCHEMA_TYPE_ALL:
821 fprintf(output, "all ");
822 break;
823 case XML_SCHEMA_TYPE_UR:
824 fprintf(output, "ur ");
825 break;
826 case XML_SCHEMA_TYPE_RESTRICTION:
827 fprintf(output, "restriction ");
828 break;
829 case XML_SCHEMA_TYPE_EXTENSION:
830 fprintf(output, "extension ");
831 break;
832 default:
833 fprintf(output, "unknowntype%d ", type->type);
834 break;
835 }
836 if (type->base != NULL) {
837 fprintf(output, "base %s, ", type->base);
838 }
839 switch (type->contentType) {
840 case XML_SCHEMA_CONTENT_UNKNOWN:
841 fprintf(output, "unknown ");
842 break;
843 case XML_SCHEMA_CONTENT_EMPTY:
844 fprintf(output, "empty ");
845 break;
846 case XML_SCHEMA_CONTENT_ELEMENTS:
847 fprintf(output, "element ");
848 break;
849 case XML_SCHEMA_CONTENT_MIXED:
850 fprintf(output, "mixed ");
851 break;
852 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
853 fprintf(output, "mixed_or_elems ");
854 break;
855 case XML_SCHEMA_CONTENT_BASIC:
856 fprintf(output, "basic ");
857 break;
858 case XML_SCHEMA_CONTENT_SIMPLE:
859 fprintf(output, "simple ");
860 break;
861 case XML_SCHEMA_CONTENT_ANY:
862 fprintf(output, "any ");
863 break;
864 }
865 fprintf(output, "\n");
866 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
867 fprintf(output, " ");
868 if (type->minOccurs != 1)
869 fprintf(output, "min: %d ", type->minOccurs);
870 if (type->maxOccurs >= UNBOUNDED)
871 fprintf(output, "max: unbounded\n");
872 else if (type->maxOccurs != 1)
873 fprintf(output, "max: %d\n", type->maxOccurs);
874 else
875 fprintf(output, "\n");
876 }
877 if (type->annot != NULL)
878 xmlSchemaAnnotDump(output, type->annot);
879 if (type->subtypes != NULL) {
880 xmlSchemaTypePtr sub = type->subtypes;
881
882 fprintf(output, " subtypes: ");
883 while (sub != NULL) {
884 fprintf(output, "%s ", sub->name);
885 sub = sub->next;
886 }
887 fprintf(output, "\n");
888 }
889
890 }
891
892 /**
893 * xmlSchemaDump:
894 * @param output the file output
895 * @param schema a schema structure
896 *
897 * Dump a Schema structure.
898 */
899 void
xmlSchemaDump(FILE * output,xmlSchemaPtr schema)900 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
901 {
902 if (schema == NULL) {
903 fprintf(output, "Schemas: NULL\n");
904 return;
905 }
906 fprintf(output, "Schemas: ");
907 if (schema->name != NULL)
908 fprintf(output, "%s, ", schema->name);
909 else
910 fprintf(output, "no name, ");
911 if (schema->targetNamespace != NULL)
912 fprintf(output, "%s", (const char *) schema->targetNamespace);
913 else
914 fprintf(output, "no target namespace");
915 fprintf(output, "\n");
916 if (schema->annot != NULL)
917 xmlSchemaAnnotDump(output, schema->annot);
918
919 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
920 output);
921 xmlHashScanFull(schema->elemDecl,
922 (xmlHashScannerFull) xmlSchemaElementDump, output);
923 }
924 #endif /* LIBXML_OUTPUT_ENABLED */
925
926 /************************************************************************
927 * *
928 * Utilities *
929 * *
930 ************************************************************************/
931
932 /**
933 * xmlSchemaGetProp:
934 * @param ctxt the parser context
935 * @param node the node
936 * @param name the property name
937 *
938 * Read a attribute value and internalize the string
939 *
940 * Returns the string or NULL if not present.
941 */
942 static const xmlChar *
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name)943 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
944 const char *name)
945 {
946 xmlChar *val;
947 const xmlChar *ret;
948
949 val = xmlGetProp(node, BAD_CAST name);
950 if (val == NULL)
951 return(NULL);
952 ret = xmlDictLookup(ctxt->dict, val, -1);
953 xmlFree(val);
954 return(ret);
955 }
956
957 #if 0
958 /**
959 * xmlSchemaGetNamespace:
960 * @param ctxt the parser context
961 * @param schema the schemas containing the declaration
962 * @param node the node
963 * @param qname the QName to analyze
964 *
965 * Find the namespace name for the given declaration.
966 *
967 * Returns the local name for that declaration, as well as the namespace name
968 * NOTE: This function is no longer used (Buchcik, May '04)
969 */
970 static const xmlChar *
971 xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
972 xmlNodePtr node, const xmlChar *qname,
973 const xmlChar **namespace) {
974 int len;
975 const xmlChar *name, *prefix, *def = NULL;
976 xmlNsPtr ns;
977
978 *namespace = NULL;
979
980 /* The following seems to be not correct here:
981 * 1. The name of a declaration is a NCName, not a QName.
982 * 2. The attribute "targetNamespace" is allowed for the
983 * <schema> Element Information Item only.
984 * 3. One cannot evaluate the target namespace, by the type
985 * of declaration, since it is dependant on the xxxFormDefault
986 * of <schema> and the form attribute of an <element> or <attribute>.
987 */
988
989 if (xmlStrEqual(node->name, BAD_CAST "element") ||
990 xmlStrEqual(node->name, BAD_CAST "attribute") ||
991 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
992 xmlStrEqual(node->name, BAD_CAST "complexType")) {
993 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
994 }
995
996
997 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
998 name = xmlSplitQName3(qname, &len);
999 if (name == NULL) {
1000 if (def == NULL) {
1001 if (xmlStrEqual(node->name, BAD_CAST "element")) {
1002 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
1003 *namespace = schema->targetNamespace;
1004 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
1005 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
1006 *namespace = schema->targetNamespace;
1007 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
1008 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
1009 *namespace = schema->targetNamespace;
1010 }
1011 } else {
1012 *namespace = def;
1013 }
1014 return(qname);
1015 }
1016
1017 name = xmlDictLookup(ctxt->dict, name, -1);
1018 prefix = xmlDictLookup(ctxt->dict, qname, len);
1019 if (def != NULL) {
1020 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
1021 "%s: presence of both prefix %s and targetNamespace\n",
1022 node->name, prefix);
1023 }
1024 ns = xmlSearchNs(node->doc, node, prefix);
1025 if (ns == NULL) {
1026 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1027 "%s: the QName prefix %s is undefined\n",
1028 node->name, prefix);
1029 return(name);
1030 }
1031 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1032 return(name);
1033 }
1034 #endif
1035
1036 /************************************************************************
1037 * *
1038 * Parsing functions *
1039 * *
1040 ************************************************************************/
1041
1042 /**
1043 * xmlSchemaGetElem:
1044 * @param schema the schemas context
1045 * @param name the element name
1046 * @param ns the element namespace
1047 * @param level how deep is the request
1048 *
1049 * Lookup a an element in the schemas or the accessible schemas
1050 *
1051 * Returns the element definition or NULL if not found.
1052 */
1053 static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * namespace,int level)1054 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
1055 const xmlChar * namespace, int level)
1056 {
1057 xmlSchemaElementPtr ret;
1058 xmlSchemaImportPtr import = NULL;
1059
1060 if ((name == NULL) || (schema == NULL))
1061 return (NULL);
1062
1063 if (namespace == NULL) {
1064 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
1065 if ((ret != NULL) &&
1066 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
1067 return (ret);
1068 }
1069 /*
1070 * This one was removed, since top level element declarations have
1071 * the target namespace specified in targetNamespace of the <schema>
1072 * information element, even if elementFormDefault is "unqualified".
1073 */
1074
1075 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
1076 if (xmlStrEqual(namespace, schema->targetNamespace))
1077 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1078 else
1079 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
1080 if ((ret != NULL) &&
1081 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
1082 return (ret);
1083 }
1084 */
1085 } else {
1086 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
1087 if ((ret != NULL) &&
1088 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
1089 return (ret);
1090 }
1091 }
1092 if (level > 0)
1093 import = xmlHashLookup(schema->schemasImports, namespace);
1094 if (import != NULL)
1095 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
1096 #ifdef DEBUG
1097 if (ret == NULL) {
1098 if (namespace == NULL)
1099 fprintf(stderr, "Unable to lookup type %s", name);
1100 else
1101 fprintf(stderr, "Unable to lookup type %s:%s", name,
1102 namespace);
1103 }
1104 #endif
1105 return (ret);
1106 }
1107
1108 /**
1109 * xmlSchemaGetType:
1110 * @param schema the schemas context
1111 * @param name the type name
1112 * @param ns the type namespace
1113 *
1114 * Lookup a type in the schemas or the predefined types
1115 *
1116 * Returns the group definition or NULL if not found.
1117 */
1118 static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * namespace)1119 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
1120 const xmlChar * namespace)
1121 {
1122 xmlSchemaTypePtr ret;
1123 xmlSchemaImportPtr import;
1124
1125 if (name == NULL)
1126 return (NULL);
1127 if (schema != NULL) {
1128 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
1129 if (ret != NULL)
1130 return (ret);
1131 }
1132 ret = xmlSchemaGetPredefinedType(name, namespace);
1133 if (ret != NULL)
1134 return (ret);
1135 import = xmlHashLookup(schema->schemasImports, namespace);
1136 if (import != NULL)
1137 ret = xmlSchemaGetType(import->schema, name, namespace);
1138 #ifdef DEBUG
1139 if (ret == NULL) {
1140 if (namespace == NULL)
1141 fprintf(stderr, "Unable to lookup type %s", name);
1142 else
1143 fprintf(stderr, "Unable to lookup type %s:%s", name,
1144 namespace);
1145 }
1146 #endif
1147 return (ret);
1148 }
1149
1150 /************************************************************************
1151 * *
1152 * Parsing functions *
1153 * *
1154 ************************************************************************/
1155
1156 #define IS_BLANK_NODE(n) \
1157 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1158
1159 /**
1160 * xmlSchemaIsBlank:
1161 * @param str a string
1162 *
1163 * Check if a string is ignorable
1164 *
1165 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1166 */
1167 static int
xmlSchemaIsBlank(xmlChar * str)1168 xmlSchemaIsBlank(xmlChar * str)
1169 {
1170 if (str == NULL)
1171 return (1);
1172 while (*str != 0) {
1173 if (!(IS_BLANK_CH(*str)))
1174 return (0);
1175 str++;
1176 }
1177 return (1);
1178 }
1179
1180 /**
1181 * xmlSchemaAddNotation:
1182 * @param ctxt a schema validation context
1183 * @param schema the schema being built
1184 * @param name the item name
1185 *
1186 * Add an XML schema Attrribute declaration
1187 * *WARNING* this interface is highly subject to change
1188 *
1189 * Returns the new struture or NULL in case of error
1190 */
1191 static xmlSchemaNotationPtr
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name)1192 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1193 const xmlChar * name)
1194 {
1195 xmlSchemaNotationPtr ret = NULL;
1196 int val;
1197
1198 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1199 return (NULL);
1200
1201 if (schema->notaDecl == NULL)
1202 schema->notaDecl = xmlHashCreate(10);
1203 if (schema->notaDecl == NULL)
1204 return (NULL);
1205
1206 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1207 if (ret == NULL) {
1208 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
1209 return (NULL);
1210 }
1211 memset(ret, 0, sizeof(xmlSchemaNotation));
1212 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1213 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1214 ret);
1215 if (val != 0) {
1216 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1217 XML_SCHEMAP_REDEFINED_NOTATION,
1218 "Notation %s already defined\n",
1219 name, NULL);
1220 xmlFree(ret);
1221 return (NULL);
1222 }
1223 return (ret);
1224 }
1225
1226
1227 /**
1228 * xmlSchemaAddAttribute:
1229 * @param ctxt a schema validation context
1230 * @param schema the schema being built
1231 * @param name the item name
1232 * @param namespace the namespace
1233 *
1234 * Add an XML schema Attrribute declaration
1235 * *WARNING* this interface is highly subject to change
1236 *
1237 * Returns the new struture or NULL in case of error
1238 */
1239 static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * namespace)1240 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1241 const xmlChar * name, const xmlChar * namespace)
1242 {
1243 xmlSchemaAttributePtr ret = NULL;
1244 int val;
1245
1246 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1247 return (NULL);
1248
1249 #ifdef DEBUG
1250 fprintf(stderr, "Adding attribute %s\n", name);
1251 if (namespace != NULL)
1252 fprintf(stderr, " target namespace %s\n", namespace);
1253 #endif
1254
1255 if (schema->attrDecl == NULL)
1256 schema->attrDecl = xmlHashCreate(10);
1257 if (schema->attrDecl == NULL)
1258 return (NULL);
1259
1260 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1261 if (ret == NULL) {
1262 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
1263 return (NULL);
1264 }
1265 memset(ret, 0, sizeof(xmlSchemaAttribute));
1266 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1267 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
1268 val = xmlHashAddEntry3(schema->attrDecl, name,
1269 schema->targetNamespace, ctxt->container, ret);
1270 if (val != 0) {
1271 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1272 XML_SCHEMAP_REDEFINED_ATTR,
1273 "Attribute %s already defined\n",
1274 name, NULL);
1275 xmlFree(ret);
1276 return (NULL);
1277 }
1278 return (ret);
1279 }
1280
1281 /**
1282 * xmlSchemaAddAttributeGroup:
1283 * @param ctxt a schema validation context
1284 * @param schema the schema being built
1285 * @param name the item name
1286 *
1287 * Add an XML schema Attrribute Group declaration
1288 *
1289 * Returns the new struture or NULL in case of error
1290 */
1291 static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name)1292 xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1293 xmlSchemaPtr schema, const xmlChar * name)
1294 {
1295 xmlSchemaAttributeGroupPtr ret = NULL;
1296 int val;
1297
1298 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1299 return (NULL);
1300
1301 if (schema->attrgrpDecl == NULL)
1302 schema->attrgrpDecl = xmlHashCreate(10);
1303 if (schema->attrgrpDecl == NULL)
1304 return (NULL);
1305
1306 ret =
1307 (xmlSchemaAttributeGroupPtr)
1308 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
1309 if (ret == NULL) {
1310 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
1311 return (NULL);
1312 }
1313 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
1314 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1315 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
1316 schema->targetNamespace, ctxt->container, ret);
1317 if (val != 0) {
1318 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1319 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1320 "Attribute group %s already defined\n",
1321 name, NULL);
1322 xmlFree(ret);
1323 return (NULL);
1324 }
1325 return (ret);
1326 }
1327
1328 /**
1329 * xmlSchemaAddElement:
1330 * @param ctxt a schema validation context
1331 * @param schema the schema being built
1332 * @param name the type name
1333 * @param namespace the type namespace
1334 *
1335 * Add an XML schema Element declaration
1336 * *WARNING* this interface is highly subject to change
1337 *
1338 * Returns the new struture or NULL in case of error
1339 */
1340 static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * namespace)1341 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1342 const xmlChar * name, const xmlChar * namespace)
1343 {
1344 xmlSchemaElementPtr ret = NULL;
1345 int val;
1346
1347 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1348 return (NULL);
1349
1350 #ifdef DEBUG
1351 fprintf(stderr, "Adding element %s\n", name);
1352 if (namespace != NULL)
1353 fprintf(stderr, " target namespace %s\n", namespace);
1354 #endif
1355
1356 if (schema->elemDecl == NULL)
1357 schema->elemDecl = xmlHashCreate(10);
1358 if (schema->elemDecl == NULL)
1359 return (NULL);
1360
1361 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1362 if (ret == NULL) {
1363 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
1364 return (NULL);
1365 }
1366 memset(ret, 0, sizeof(xmlSchemaElement));
1367 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1368 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
1369 val = xmlHashAddEntry3(schema->elemDecl, name,
1370 namespace, ctxt->container, ret);
1371 if (val != 0) {
1372 char buf[100];
1373
1374 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
1375 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1376 namespace, ret);
1377 if (val != 0) {
1378 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1379 XML_SCHEMAP_REDEFINED_ELEMENT,
1380 "Element %s already defined\n",
1381 name, NULL);
1382 xmlFree(ret);
1383 return (NULL);
1384 }
1385 }
1386 return (ret);
1387 }
1388
1389 /**
1390 * xmlSchemaAddType:
1391 * @param ctxt a schema validation context
1392 * @param schema the schema being built
1393 * @param name the item name
1394 * @param namespace the namespace
1395 *
1396 * Add an XML schema Simple Type definition
1397 * *WARNING* this interface is highly subject to change
1398 *
1399 * Returns the new struture or NULL in case of error
1400 */
1401 static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * namespace)1402 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1403 const xmlChar * name, const xmlChar * namespace)
1404 {
1405 xmlSchemaTypePtr ret = NULL;
1406 int val;
1407
1408 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1409 return (NULL);
1410
1411 #ifdef DEBUG
1412 fprintf(stderr, "Adding type %s\n", name);
1413 if (namespace != NULL)
1414 fprintf(stderr, " target namespace %s\n", namespace);
1415 #endif
1416
1417 if (schema->typeDecl == NULL)
1418 schema->typeDecl = xmlHashCreate(10);
1419 if (schema->typeDecl == NULL)
1420 return (NULL);
1421
1422 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1423 if (ret == NULL) {
1424 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
1425 return (NULL);
1426 }
1427 memset(ret, 0, sizeof(xmlSchemaType));
1428 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1429 ret->redef = NULL;
1430 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
1431 if (val != 0) {
1432 if (ctxt->includes == 0) {
1433 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1434 XML_SCHEMAP_REDEFINED_TYPE,
1435 "Type %s already defined\n",
1436 name, NULL);
1437 xmlFree(ret);
1438 return (NULL);
1439 } else {
1440 xmlSchemaTypePtr prev;
1441
1442 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1443 if (prev == NULL) {
1444 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1445 XML_ERR_INTERNAL_ERROR,
1446 "Internal error on type %s definition\n",
1447 name, NULL);
1448 xmlFree(ret);
1449 return (NULL);
1450 }
1451 ret->redef = prev->redef;
1452 prev->redef = ret;
1453 }
1454 }
1455 ret->minOccurs = 1;
1456 ret->maxOccurs = 1;
1457
1458 return (ret);
1459 }
1460
1461 /**
1462 * xmlSchemaAddGroup:
1463 * @param ctxt a schema validation context
1464 * @param schema the schema being built
1465 * @param name the group name
1466 *
1467 * Add an XML schema Group definition
1468 *
1469 * Returns the new struture or NULL in case of error
1470 */
1471 static xmlSchemaTypePtr
xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name)1472 xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1473 const xmlChar * name)
1474 {
1475 xmlSchemaTypePtr ret = NULL;
1476 int val;
1477
1478 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1479 return (NULL);
1480
1481 if (schema->groupDecl == NULL)
1482 schema->groupDecl = xmlHashCreate(10);
1483 if (schema->groupDecl == NULL)
1484 return (NULL);
1485
1486 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1487 if (ret == NULL) {
1488 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
1489 return (NULL);
1490 }
1491 memset(ret, 0, sizeof(xmlSchemaType));
1492 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1493 val =
1494 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1495 ret);
1496 if (val != 0) {
1497 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1498 XML_SCHEMAP_REDEFINED_GROUP,
1499 "Group %s already defined\n",
1500 name, NULL);
1501 xmlFree(ret);
1502 return (NULL);
1503 }
1504 ret->minOccurs = 1;
1505 ret->maxOccurs = 1;
1506
1507 return (ret);
1508 }
1509
1510 /************************************************************************
1511 * *
1512 * Utilities for parsing *
1513 * *
1514 ************************************************************************/
1515
1516 /**
1517 * xmlGetQNameProp:
1518 * @param ctxt a schema validation context
1519 * @param node a subtree containing XML Schema informations
1520 * @param name the attribute name
1521 * @param namespace the result namespace if any
1522 *
1523 * Extract a QName Attribute value
1524 *
1525 * Returns the NCName or NULL if not found, and also update @namespace
1526 * with the namespace URI
1527 */
1528 static const xmlChar *
xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,const xmlChar ** namespace)1529 xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1530 const char *name, const xmlChar ** namespace)
1531 {
1532 const xmlChar *val;
1533 xmlNsPtr ns;
1534 const xmlChar *ret, *prefix;
1535 int len;
1536
1537 *namespace = NULL;
1538 val = xmlSchemaGetProp(ctxt, node, name);
1539 if (val == NULL)
1540 return (NULL);
1541
1542 if (!strchr((char *) val, ':')) {
1543 ns = xmlSearchNs(node->doc, node, 0);
1544 if (ns) {
1545 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1546 return (val);
1547 }
1548 }
1549 ret = xmlSplitQName3(val, &len);
1550 if (ret == NULL) {
1551 return (val);
1552 }
1553 ret = xmlDictLookup(ctxt->dict, ret, -1);
1554 prefix = xmlDictLookup(ctxt->dict, val, len);
1555
1556 ns = xmlSearchNs(node->doc, node, prefix);
1557 if (ns == NULL) {
1558 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1559 "Attribute %s: the QName prefix %s is undefined\n",
1560 (const xmlChar *) name, prefix);
1561 } else {
1562 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1563 }
1564 return (ret);
1565 }
1566
1567 /**
1568 * xmlGetMaxOccurs:
1569 * @param ctxt a schema validation context
1570 * @param node a subtree containing XML Schema informations
1571 *
1572 * Get the maxOccurs property
1573 *
1574 * Returns the default if not found, or the value
1575 */
1576 static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)1577 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1578 {
1579 const xmlChar *val, *cur;
1580 int ret = 0;
1581
1582 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
1583 if (val == NULL)
1584 return (1);
1585
1586 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
1587 return (UNBOUNDED); /* encoding it with -1 might be another option */
1588 }
1589
1590 cur = val;
1591 while (IS_BLANK_CH(*cur))
1592 cur++;
1593 while ((*cur >= '0') && (*cur <= '9')) {
1594 ret = ret * 10 + (*cur - '0');
1595 cur++;
1596 }
1597 while (IS_BLANK_CH(*cur))
1598 cur++;
1599 if (*cur != 0) {
1600 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1601 "invalid value for maxOccurs: %s\n", val, NULL);
1602 return (1);
1603 }
1604 return (ret);
1605 }
1606
1607 /**
1608 * xmlGetMinOccurs:
1609 * @param ctxt a schema validation context
1610 * @param node a subtree containing XML Schema informations
1611 *
1612 * Get the minOccurs property
1613 *
1614 * Returns the default if not found, or the value
1615 */
1616 static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)1617 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1618 {
1619 const xmlChar *val, *cur;
1620 int ret = 0;
1621
1622 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
1623 if (val == NULL)
1624 return (1);
1625
1626 cur = val;
1627 while (IS_BLANK_CH(*cur))
1628 cur++;
1629 while ((*cur >= '0') && (*cur <= '9')) {
1630 ret = ret * 10 + (*cur - '0');
1631 cur++;
1632 }
1633 while (IS_BLANK_CH(*cur))
1634 cur++;
1635 if (*cur != 0) {
1636 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1637 "invalid value for minOccurs: %s\n", val, NULL);
1638 return (1);
1639 }
1640 return (ret);
1641 }
1642
1643 /**
1644 * xmlGetBooleanProp:
1645 * @param ctxt a schema validation context
1646 * @param node a subtree containing XML Schema informations
1647 * @param name the attribute name
1648 * @param def the default value
1649 *
1650 * Get is a bolean property is set
1651 *
1652 * Returns the default if not found, 0 if found to be false,
1653 * 1 if found to be true
1654 */
1655 static int
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,int def)1656 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1657 const char *name, int def)
1658 {
1659 const xmlChar *val;
1660
1661 val = xmlSchemaGetProp(ctxt, node, name);
1662 if (val == NULL)
1663 return (def);
1664
1665 if (xmlStrEqual(val, BAD_CAST "true"))
1666 def = 1;
1667 else if (xmlStrEqual(val, BAD_CAST "false"))
1668 def = 0;
1669 else {
1670 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1671 "Attribute %s: the value %s is not boolean\n",
1672 (const xmlChar *) name, val);
1673 }
1674 return (def);
1675 }
1676
1677 /************************************************************************
1678 * *
1679 * Shema extraction from an Infoset *
1680 * *
1681 ************************************************************************/
1682 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1683 ctxt, xmlSchemaPtr schema,
1684 xmlNodePtr node);
1685 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1686 ctxt,
1687 xmlSchemaPtr schema,
1688 xmlNodePtr node);
1689 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1690 ctxt,
1691 xmlSchemaPtr schema,
1692 xmlNodePtr node,
1693 int simple);
1694 static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1695 xmlSchemaPtr schema,
1696 xmlNodePtr node);
1697 static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1698 xmlSchemaPtr schema,
1699 xmlNodePtr node);
1700 static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1701 ctxt,
1702 xmlSchemaPtr schema,
1703 xmlNodePtr node,
1704 int topLevel);
1705 static xmlSchemaAttributeGroupPtr
1706 xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1707 xmlSchemaPtr schema, xmlNodePtr node);
1708 static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1709 xmlSchemaPtr schema,
1710 xmlNodePtr node);
1711 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1712 xmlSchemaPtr schema,
1713 xmlNodePtr node);
1714 static xmlSchemaAttributePtr
1715 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1716 xmlSchemaPtr schema, xmlNodePtr node);
1717
1718 /**
1719 * xmlSchemaParseAttrDecls:
1720 * @param ctxt a schema validation context
1721 * @param schema the schema being built
1722 * @param node a subtree containing XML Schema informations
1723 * @param type the hosting type
1724 *
1725 * parse a XML schema attrDecls declaration corresponding to
1726 * <!ENTITY % attrDecls
1727 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1728 */
1729 static xmlNodePtr
xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr child,xmlSchemaTypePtr type)1730 xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1731 xmlNodePtr child, xmlSchemaTypePtr type)
1732 {
1733 xmlSchemaAttributePtr lastattr, attr;
1734
1735 lastattr = NULL;
1736 while ((IS_SCHEMA(child, "attribute")) ||
1737 (IS_SCHEMA(child, "attributeGroup"))) {
1738 attr = NULL;
1739 if (IS_SCHEMA(child, "attribute")) {
1740 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
1741 } else if (IS_SCHEMA(child, "attributeGroup")) {
1742 attr = (xmlSchemaAttributePtr)
1743 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1744 }
1745 if (attr != NULL) {
1746 if (lastattr == NULL) {
1747 type->attributes = attr;
1748 lastattr = attr;
1749 } else {
1750 lastattr->next = attr;
1751 lastattr = attr;
1752 }
1753 }
1754 child = child->next;
1755 }
1756 if (IS_SCHEMA(child, "anyAttribute")) {
1757 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1758 if (attr != NULL) {
1759 if (lastattr == NULL) {
1760 type->attributes = attr;
1761 lastattr = attr;
1762 } else {
1763 lastattr->next = attr;
1764 lastattr = attr;
1765 }
1766 }
1767 child = child->next;
1768 }
1769 return (child);
1770 }
1771
1772 /**
1773 * xmlSchemaParseAnnotation:
1774 * @param ctxt a schema validation context
1775 * @param schema the schema being built
1776 * @param node a subtree containing XML Schema informations
1777 *
1778 * parse a XML schema Attrribute declaration
1779 * *WARNING* this interface is highly subject to change
1780 *
1781 * Returns -1 in case of error, 0 if the declaration is improper and
1782 * 1 in case of success.
1783 */
1784 static xmlSchemaAnnotPtr
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)1785 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1786 xmlNodePtr node)
1787 {
1788 xmlSchemaAnnotPtr ret;
1789
1790 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1791 return (NULL);
1792 ret = xmlSchemaNewAnnot(ctxt, node);
1793
1794 return (ret);
1795 }
1796
1797 /**
1798 * xmlSchemaParseFacet:
1799 * @param ctxt a schema validation context
1800 * @param schema the schema being built
1801 * @param node a subtree containing XML Schema informations
1802 *
1803 * parse a XML schema Facet declaration
1804 * *WARNING* this interface is highly subject to change
1805 *
1806 * Returns the new type structure or NULL in case of error
1807 */
1808 static xmlSchemaFacetPtr
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)1809 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1810 xmlNodePtr node)
1811 {
1812 xmlSchemaFacetPtr facet;
1813 xmlNodePtr child = NULL;
1814 const xmlChar *value;
1815
1816 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1817 return (NULL);
1818
1819 facet = xmlSchemaNewFacet();
1820 if (facet == NULL) {
1821 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1822 return (NULL);
1823 }
1824 facet->node = node;
1825 value = xmlSchemaGetProp(ctxt, node, "value");
1826 if (value == NULL) {
1827 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1828 "Facet %s has no value\n", node->name, NULL);
1829 xmlSchemaFreeFacet(facet);
1830 return (NULL);
1831 }
1832 if (IS_SCHEMA(node, "minInclusive")) {
1833 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
1834 } else if (IS_SCHEMA(node, "minExclusive")) {
1835 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
1836 } else if (IS_SCHEMA(node, "maxInclusive")) {
1837 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
1838 } else if (IS_SCHEMA(node, "maxExclusive")) {
1839 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
1840 } else if (IS_SCHEMA(node, "totalDigits")) {
1841 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
1842 } else if (IS_SCHEMA(node, "fractionDigits")) {
1843 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
1844 } else if (IS_SCHEMA(node, "pattern")) {
1845 facet->type = XML_SCHEMA_FACET_PATTERN;
1846 } else if (IS_SCHEMA(node, "enumeration")) {
1847 facet->type = XML_SCHEMA_FACET_ENUMERATION;
1848 } else if (IS_SCHEMA(node, "whiteSpace")) {
1849 facet->type = XML_SCHEMA_FACET_WHITESPACE;
1850 } else if (IS_SCHEMA(node, "length")) {
1851 facet->type = XML_SCHEMA_FACET_LENGTH;
1852 } else if (IS_SCHEMA(node, "maxLength")) {
1853 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1854 } else if (IS_SCHEMA(node, "minLength")) {
1855 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1856 } else {
1857 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1858 "Unknown facet type %s\n", node->name, NULL);
1859 xmlSchemaFreeFacet(facet);
1860 return (NULL);
1861 }
1862 facet->id = xmlSchemaGetProp(ctxt, node, "id");
1863 facet->value = value;
1864 child = node->children;
1865
1866 if (IS_SCHEMA(child, "annotation")) {
1867 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1868 child = child->next;
1869 }
1870 if (child != NULL) {
1871 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1872 "Facet %s has unexpected child content\n",
1873 node->name, NULL);
1874 }
1875 return (facet);
1876 }
1877
1878 /**
1879 * xmlSchemaParseAny:
1880 * @param ctxt a schema validation context
1881 * @param schema the schema being built
1882 * @param node a subtree containing XML Schema informations
1883 *
1884 * parse a XML schema Any declaration
1885 * *WARNING* this interface is highly subject to change
1886 *
1887 * Returns the new type structure or NULL in case of error
1888 */
1889 static xmlSchemaTypePtr
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)1890 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1891 xmlNodePtr node)
1892 {
1893 xmlSchemaTypePtr type;
1894 xmlNodePtr child = NULL;
1895 xmlChar name[30];
1896
1897 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1898 return (NULL);
1899 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
1900 type = xmlSchemaAddType(ctxt, schema, name, NULL);
1901 if (type == NULL)
1902 return (NULL);
1903 type->node = node;
1904 type->type = XML_SCHEMA_TYPE_ANY;
1905 child = node->children;
1906 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1907 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1908
1909 if (IS_SCHEMA(child, "annotation")) {
1910 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1911 child = child->next;
1912 }
1913 if (child != NULL) {
1914 xmlSchemaPErr2(ctxt, node, child,
1915 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1916 "Sequence %s has unexpected content\n", type->name,
1917 NULL);
1918 }
1919
1920 return (type);
1921 }
1922
1923 /**
1924 * xmlSchemaParseNotation:
1925 * @param ctxt a schema validation context
1926 * @param schema the schema being built
1927 * @param node a subtree containing XML Schema informations
1928 *
1929 * parse a XML schema Notation declaration
1930 *
1931 * Returns the new structure or NULL in case of error
1932 */
1933 static xmlSchemaNotationPtr
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)1934 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1935 xmlNodePtr node)
1936 {
1937 const xmlChar *name;
1938 xmlSchemaNotationPtr ret;
1939 xmlNodePtr child = NULL;
1940
1941 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1942 return (NULL);
1943 name = xmlSchemaGetProp(ctxt, node, "name");
1944 if (name == NULL) {
1945 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1946 "Notation has no name\n", NULL, NULL);
1947 return (NULL);
1948 }
1949 ret = xmlSchemaAddNotation(ctxt, schema, name);
1950 if (ret == NULL) {
1951 return (NULL);
1952 }
1953 child = node->children;
1954 if (IS_SCHEMA(child, "annotation")) {
1955 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1956 child = child->next;
1957 }
1958 if (child != NULL) {
1959 xmlSchemaPErr2(ctxt, node, child,
1960 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1961 "notation %s has unexpected content\n", name, NULL);
1962 }
1963
1964 return (ret);
1965 }
1966
1967 /**
1968 * xmlSchemaParseAnyAttribute:
1969 * @param ctxt a schema validation context
1970 * @param schema the schema being built
1971 * @param node a subtree containing XML Schema informations
1972 *
1973 * parse a XML schema AnyAttrribute declaration
1974 * *WARNING* this interface is highly subject to change
1975 *
1976 * Returns an attribute def structure or NULL
1977 */
1978 static xmlSchemaAttributePtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)1979 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1980 xmlSchemaPtr schema, xmlNodePtr node)
1981 {
1982 const xmlChar *processContents;
1983 xmlSchemaAttributePtr ret;
1984 xmlNodePtr child = NULL;
1985 char name[100];
1986
1987
1988 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1989 return (NULL);
1990
1991 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
1992
1993 /* local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns); */
1994
1995 /*
1996 * namespace = ((##any | ##other) | List of (anyURI |
1997 * (##targetNamespace | * ##local)) ) : ##any
1998 */
1999 ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, NULL);
2000 if (ret == NULL) {
2001 return (NULL);
2002 }
2003 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
2004 ret->id = xmlSchemaGetProp(ctxt, node, "id");
2005 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
2006 if ((processContents == NULL)
2007 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
2008 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
2009 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
2010 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
2011 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
2012 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
2013 } else {
2014 xmlSchemaPErr2(ctxt, node, child,
2015 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
2016 "anyAttribute has unexpected content "
2017 "for processContents: %s\n",
2018 processContents, NULL);
2019 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
2020 }
2021
2022 child = node->children;
2023 if (IS_SCHEMA(child, "annotation")) {
2024 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2025 child = child->next;
2026 }
2027 if (child != NULL) {
2028 xmlSchemaPErr2(ctxt, node, child,
2029 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
2030 "anyAttribute %s has unexpected content\n",
2031 (const xmlChar *) name, NULL);
2032 }
2033
2034 return (ret);
2035 }
2036
2037
2038 /**
2039 * xmlSchemaParseAttribute:
2040 * @param ctxt a schema validation context
2041 * @param schema the schema being built
2042 * @param node a subtree containing XML Schema informations
2043 *
2044 * parse a XML schema Attrribute declaration
2045 * *WARNING* this interface is highly subject to change
2046 *
2047 * Returns the attribute declaration.
2048 */
2049 static xmlSchemaAttributePtr
xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)2050 xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2051 xmlNodePtr node, int topLevel)
2052 {
2053 const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal;
2054 xmlSchemaAttributePtr ret;
2055 xmlNodePtr child = NULL;
2056 char buf[100];
2057 int hasRefType = 0;
2058
2059 /*
2060 * Note that the w3c spec assumes the schema to be validated with schema
2061 * for schemas beforehand.
2062 *
2063 * 3.2.3 Constraints on XML Representations of Attribute Declarations
2064 *
2065 * Complete implementation of:
2066 * 3.2.6 Schema Component Constraint: Attribute Declaration Properties
2067 * Correct
2068 */
2069
2070 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2071 return (NULL);
2072
2073 name = xmlSchemaGetProp(ctxt, node, "name");
2074 if (name == NULL) {
2075 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2076 /* 3.2.3 : 3.1
2077 * One of ref or name must be present, but not both
2078 */
2079 if (ref == NULL) {
2080 xmlSchemaPErr(ctxt, node,
2081 XML_SCHEMAP_ATTR_NONAME_NOREF,
2082 "Attribute declaration has no \"name\" or \"ref\"\n",
2083 NULL, NULL);
2084 return (NULL);
2085 }
2086 hasRefType = 1;
2087 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2088 name = (const xmlChar *) buf;
2089 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
2090 if (!topLevel) {
2091 /* 3.2.3 : 3.2
2092 * If ref is present, then all of <simpleType>,
2093 * form and type must be absent.
2094 */
2095 if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2096 xmlSchemaPErr(ctxt, node,
2097 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2098 "Attribute declaration %s has \"ref\", thus "
2099 "\"form\" must be absent\n", name, NULL);
2100 }
2101 if (xmlSchemaGetProp(ctxt, node, "type") != NULL) {
2102 xmlSchemaPErr(ctxt, node,
2103 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2104 "Attribute declaration %s has \"ref\", thus "
2105 "\"type\" must be absent\n", name, NULL);
2106 }
2107 }
2108 } else {
2109 const xmlChar *ns = NULL;
2110 /* 3.2.3 : 3.1
2111 * One of ref or name must be present, but not both
2112 */
2113 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2114 xmlSchemaPErr(ctxt, node,
2115 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2116 "Attribute declaration has both, \"name\" and "
2117 "\"ref\"\n", NULL, NULL);
2118 }
2119
2120 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2121 /* Evaluate the target namespace */
2122 if (schema->targetNamespace != NULL) {
2123 if (topLevel) {
2124 ns = schema->targetNamespace;
2125 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2126 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2127 BAD_CAST "qualified")) {
2128 ns = schema->targetNamespace;
2129 }
2130 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2131 ns = schema->targetNamespace;
2132 }
2133 }
2134 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns);
2135
2136 /* 3.2.6 Schema Component Constraint: xmlns Not Allowed */
2137 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2138 xmlSchemaPErr(ctxt, node,
2139 XML_SCHEMAP_INVALID_ATTR_NAME,
2140 "The name of an attribute declaration must not match "
2141 "\"xmlns\".\n", NULL, NULL);
2142 }
2143
2144 /* 3.2.6 Schema Component Constraint: xsi: Not Allowed */
2145 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
2146 xmlSchemaPErr(ctxt, node,
2147 XML_SCHEMAP_INVALID_ATTR_NAME,
2148 "The target namespace of an attribute declaration, "
2149 "must not match \"http://www.w3.org/2001/"
2150 "XMLSchema-instance\"", NULL, NULL);
2151 }
2152 }
2153 if (ret == NULL) {
2154 return (NULL);
2155 }
2156 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
2157
2158 /* Handle the "use" attribute. */
2159 attrVal = xmlSchemaGetProp(ctxt, node, "use");
2160 if (attrVal != NULL) {
2161 if (xmlStrEqual(attrVal, BAD_CAST "optional"))
2162 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2163 else if (xmlStrEqual(attrVal, BAD_CAST "prohibited"))
2164 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
2165 else if (xmlStrEqual(attrVal, BAD_CAST "required"))
2166 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
2167 else
2168 xmlSchemaPErr(ctxt, node,
2169 XML_SCHEMAP_INVALID_ATTR_USE,
2170 "Attribute declaration %s has an invalid "
2171 "value for \"use\"\n", name, NULL);
2172 } else
2173 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2174
2175
2176 if (xmlSchemaGetProp(ctxt, node, "default") != NULL) {
2177 /* 3.2.3 : 1
2178 * default and fixed must not both be present.
2179 */
2180 if (xmlSchemaGetProp(ctxt, node, "fixed") != NULL) {
2181 xmlSchemaPErr(ctxt, node,
2182 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2183 "Attribute declaration has both, \"default\" "
2184 "and \"fixed\"\n", NULL, NULL);
2185 }
2186 /* 3.2.3 : 2
2187 * If default and use are both present, use must have
2188 * the actual value optional.
2189 */
2190 if (ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) {
2191 xmlSchemaPErr(ctxt, node,
2192 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2193 "Attribute declaration has \"default\" but "
2194 "\"use\" is not \"optional\"\n", NULL, NULL);
2195 }
2196 }
2197
2198 ret->ref = ref;
2199 ret->refNs = refNs;
2200 /*
2201 * The setting of XML_SCHEMAS_ATTR_NSDEFAULT is not needed anymore,
2202 * since the target namespace was already evaluated and took
2203 * attributeFormDefault into account.
2204 */
2205 /*
2206 if ((ret->targetNamespace != NULL) &&
2207 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2208 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2209 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
2210 */
2211 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
2212 if (ret->typeName != NULL)
2213 hasRefType = 1;
2214 ret->node = node;
2215 child = node->children;
2216 if (IS_SCHEMA(child, "annotation")) {
2217 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2218 child = child->next;
2219 }
2220 if (IS_SCHEMA(child, "simpleType")) {
2221 if (hasRefType) {
2222 /* 3.2.3 : 4
2223 * type and <simpleType> must not both be present.
2224 *
2225 *
2226 *
2227 */
2228 xmlSchemaPErr2(ctxt, node, child,
2229 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2230 "Attribute declaration %s has both (\"ref\" or "
2231 "\"type\") and <simpleType>\n", name, NULL);
2232 } else
2233 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2234 child = child->next;
2235 }
2236 if (child != NULL) {
2237 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2238 "attribute %s has unexpected content\n", name,
2239 NULL);
2240 }
2241
2242 return (ret);
2243 }
2244
2245 /**
2246 * xmlSchemaParseAttributeGroup:
2247 * @param ctxt a schema validation context
2248 * @param schema the schema being built
2249 * @param node a subtree containing XML Schema informations
2250 *
2251 * parse a XML schema Attribute Group declaration
2252 * *WARNING* this interface is highly subject to change
2253 *
2254 * Returns the attribute group or NULL in case of error.
2255 */
2256 static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2257 xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
2258 xmlSchemaPtr schema, xmlNodePtr node)
2259 {
2260 const xmlChar *name, *refNs = NULL, *ref = NULL;
2261 xmlSchemaAttributeGroupPtr ret;
2262 xmlSchemaAttributePtr last = NULL, attr;
2263 xmlNodePtr child = NULL;
2264 const xmlChar *oldcontainer;
2265 char buf[100];
2266
2267 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2268 return (NULL);
2269 oldcontainer = ctxt->container;
2270 name = xmlSchemaGetProp(ctxt, node, "name");
2271 if (name == NULL) {
2272
2273 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2274 if (ref == NULL) {
2275 xmlSchemaPErr2(ctxt, node, child,
2276 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2277 "AttributeGroup has no name nor ref\n", NULL,
2278 NULL);
2279 return (NULL);
2280 }
2281 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2282 name = (const xmlChar *) buf;
2283 if (name == NULL) {
2284 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2285 return (NULL);
2286 }
2287 }
2288 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2289 if (ret == NULL) {
2290 return (NULL);
2291 }
2292 ret->ref = ref;
2293 ret->refNs = refNs;
2294 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
2295 ret->node = node;
2296 child = node->children;
2297 ctxt->container = name;
2298 if (IS_SCHEMA(child, "annotation")) {
2299 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2300 child = child->next;
2301 }
2302 while ((IS_SCHEMA(child, "attribute")) ||
2303 (IS_SCHEMA(child, "attributeGroup"))) {
2304 attr = NULL;
2305 if (IS_SCHEMA(child, "attribute")) {
2306 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
2307 } else if (IS_SCHEMA(child, "attributeGroup")) {
2308 attr = (xmlSchemaAttributePtr)
2309 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2310 }
2311 if (attr != NULL) {
2312 if (last == NULL) {
2313 ret->attributes = attr;
2314 last = attr;
2315 } else {
2316 last->next = attr;
2317 last = attr;
2318 }
2319 }
2320 child = child->next;
2321 }
2322 if (IS_SCHEMA(child, "anyAttribute")) {
2323 TODO
2324 child = child->next;
2325 }
2326 if (child != NULL) {
2327 xmlSchemaPErr2(ctxt, node, child,
2328 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2329 "attribute group %s has unexpected content\n", name,
2330 NULL);
2331 }
2332 ctxt->container = oldcontainer;
2333 return (ret);
2334 }
2335
2336 /**
2337 * xmlSchemaParseElement:
2338 * @param ctxt a schema validation context
2339 * @param schema the schema being built
2340 * @param node a subtree containing XML Schema informations
2341 *
2342 * parse a XML schema Element declaration
2343 * *WARNING* this interface is highly subject to change
2344 *
2345 * Returns the parsed element declaration.
2346 */
2347 static xmlSchemaElementPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int toplevel)2348 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2349 xmlNodePtr node, int toplevel)
2350 {
2351 const xmlChar *name, *fixed;
2352 const xmlChar *refNs = NULL, *ref = NULL;
2353 xmlSchemaElementPtr ret;
2354 xmlNodePtr child = NULL;
2355 const xmlChar *oldcontainer;
2356 char buf[100];
2357 xmlAttrPtr attr;
2358
2359 /* 3.3.3 Constraints on XML Representations of Element Declarations */
2360
2361
2362 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2363 return (NULL);
2364 oldcontainer = ctxt->container;
2365 name = xmlSchemaGetProp(ctxt, node, "name");
2366 if (name == NULL) {
2367
2368 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2369 /* 3.3.3 : 2.1
2370 * One of ref or name must be present, but not both
2371 */
2372 if (ref == NULL) {
2373 xmlSchemaPErr(ctxt, node,
2374 XML_SCHEMAP_ELEM_NONAME_NOREF,
2375 "Element has no name nor ref\n", NULL, NULL);
2376 return (NULL);
2377 }
2378 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2379 name = (const xmlChar *) buf;
2380 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2381 } else {
2382 const xmlChar *ns = NULL;
2383
2384 /* Evaluate the target namespace */
2385 if (schema->targetNamespace != NULL) {
2386 if (toplevel) {
2387 ns = schema->targetNamespace;
2388 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2389 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2390 BAD_CAST "qualified")) {
2391 ns = schema->targetNamespace;
2392 }
2393 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2394 ns = schema->targetNamespace;
2395 }
2396 }
2397 /*local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2398 ret = xmlSchemaAddElement(ctxt, schema, name, ns);
2399 /* 3.3.3 : 2.1
2400 * One of ref or name must be present, but not both
2401 */
2402 if ((!toplevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2403 xmlSchemaPErr(ctxt, node,
2404 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2405 "Element declaration has both, \"name\" and "
2406 "\"ref\"\n", NULL, NULL);
2407 }
2408 }
2409 if (ret != NULL)
2410 ret->node = node;
2411 if (ret == NULL) {
2412 return (NULL);
2413 }
2414 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2415 ret->ref = ref;
2416 ret->refNs = refNs;
2417 if (ref != NULL)
2418 ret->flags |= XML_SCHEMAS_ELEM_REF;
2419
2420 /* 3.3.3 : 2.2 */
2421 if ((!toplevel) && (ref != NULL)) {
2422 attr = node->properties;
2423 while (attr != NULL) {
2424 if ((attr->ns == NULL) &&
2425 (!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
2426 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
2427 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
2428 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
2429
2430 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2431 "Element declaration %s: only minOccurs, maxOccurs "
2432 "and id are allowed in addition to ref\n",
2433 ret->name, NULL);
2434 }
2435 attr = attr->next;
2436 }
2437 }
2438
2439 if (toplevel)
2440 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2441 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2442 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2443 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2444 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2445 ctxt->container = name;
2446
2447 ret->id = xmlSchemaGetProp(ctxt, node, "id");
2448 ret->namedType =
2449 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
2450 ret->substGroup =
2451 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2452 &(ret->substGroupNs));
2453 if ((ret->substGroup != NULL) && (!toplevel)) {
2454 /* 3.3.6 : 3 */
2455 /*
2456 * This seems to be redundant, since the schema for schemas
2457 * already prohibits the use of the "substitutionGroup" attribute
2458 * in local element declarations.
2459 */
2460 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2461 "Element declaration %s: substitutionGroup is allowed "
2462 "on top-level declarations only\n", ret->name, NULL);
2463
2464 }
2465 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
2466 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2467 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2468
2469 ret->value = xmlSchemaGetProp(ctxt, node, "default");
2470 if ((ret->value != NULL) && (fixed != NULL)) {
2471 /* 3.3.3 : 1
2472 * default and fixed must not both be present.
2473 */
2474 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2475 "Element %s has both default and fixed\n",
2476 ret->name, NULL);
2477 } else if (fixed != NULL) {
2478 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
2479 ret->value = fixed;
2480 }
2481
2482 child = node->children;
2483 if (IS_SCHEMA(child, "annotation")) {
2484 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2485 child = child->next;
2486 }
2487 if (ref != NULL) {
2488 /* 3.3.3 (2.2) */
2489 while (child != NULL) {
2490 if ((IS_SCHEMA(child, "complexType")) ||
2491 (IS_SCHEMA(child, "simpleType")) ||
2492 (IS_SCHEMA(child, "unique")) ||
2493 (IS_SCHEMA(child, "key")) ||
2494 (IS_SCHEMA(child, "keyref"))) {
2495
2496 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_REF_AND_CONTENT,
2497 "Element declaration %s: only annotation is "
2498 "allowed as content in addition to ref\n",
2499 ret->name, NULL);
2500 } else {
2501 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2502 "element %s has unexpected content\n", name, NULL);
2503 }
2504 child = child->next;
2505 }
2506 } else {
2507 if (IS_SCHEMA(child, "complexType")) {
2508 /* 3.3.3 : 3
2509 * type and either <simpleType> or <complexType> are mutually
2510 * exclusive
2511 */
2512 if (ret->namedType != NULL) {
2513 xmlSchemaPErr2(ctxt, node, child,
2514 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2515 "Element declaration %s has both \"type\" "
2516 "and a local complex type\n",
2517 ret->name, NULL);
2518 } else
2519 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
2520 child = child->next;
2521 } else if (IS_SCHEMA(child, "simpleType")) {
2522 /* 3.3.3 : 3
2523 * type and either <simpleType> or <complexType> are
2524 * mutually exclusive
2525 */
2526 if (ret->namedType != NULL) {
2527 xmlSchemaPErr2(ctxt, node, child,
2528 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2529 "Element declaration %s has both \"type\" "
2530 "and a local simple type\n",
2531 ret->name, NULL);
2532 } else
2533 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2534 child = child->next;
2535 }
2536
2537 while ((IS_SCHEMA(child, "unique")) ||
2538 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2539 TODO child = child->next;
2540 }
2541 if (child != NULL) {
2542 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2543 "element %s has unexpected content\n", name, NULL);
2544 }
2545 }
2546
2547 ctxt->container = oldcontainer;
2548 return (ret);
2549 }
2550
2551 /**
2552 * xmlSchemaParseUnion:
2553 * @param ctxt a schema validation context
2554 * @param schema the schema being built
2555 * @param node a subtree containing XML Schema informations
2556 *
2557 * parse a XML schema Union definition
2558 * *WARNING* this interface is highly subject to change
2559 *
2560 * Returns -1 in case of error, 0 if the declaration is improper and
2561 * 1 in case of success.
2562 */
2563 static xmlSchemaTypePtr
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2564 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2565 xmlNodePtr node)
2566 {
2567 xmlSchemaTypePtr type, subtype, last = NULL;
2568 xmlNodePtr child = NULL;
2569 xmlChar name[30];
2570
2571 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2572 return (NULL);
2573
2574
2575 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
2576 type = xmlSchemaAddType(ctxt, schema, name, NULL);
2577 if (type == NULL)
2578 return (NULL);
2579 type->node = node;
2580 type->type = XML_SCHEMA_TYPE_UNION;
2581 type->id = xmlSchemaGetProp(ctxt, node, "id");
2582 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
2583
2584 child = node->children;
2585 if (IS_SCHEMA(child, "annotation")) {
2586 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2587 child = child->next;
2588 }
2589 while (IS_SCHEMA(child, "simpleType")) {
2590 subtype = (xmlSchemaTypePtr)
2591 xmlSchemaParseSimpleType(ctxt, schema, child);
2592 if (subtype != NULL) {
2593 if (last == NULL) {
2594 type->subtypes = subtype;
2595 last = subtype;
2596 } else {
2597 last->next = subtype;
2598 last = subtype;
2599 }
2600 last->next = NULL;
2601 }
2602 child = child->next;
2603 }
2604 if (child != NULL) {
2605 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2606 "Union %s has unexpected content\n", type->name,
2607 NULL);
2608 }
2609 return (type);
2610 }
2611
2612 /**
2613 * xmlSchemaParseList:
2614 * @param ctxt a schema validation context
2615 * @param schema the schema being built
2616 * @param node a subtree containing XML Schema informations
2617 *
2618 * parse a XML schema List definition
2619 * *WARNING* this interface is highly subject to change
2620 *
2621 * Returns -1 in case of error, 0 if the declaration is improper and
2622 * 1 in case of success.
2623 */
2624 static xmlSchemaTypePtr
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2625 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2626 xmlNodePtr node)
2627 {
2628 xmlSchemaTypePtr type, subtype;
2629 xmlNodePtr child = NULL;
2630 xmlChar name[30];
2631
2632 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2633 return (NULL);
2634
2635 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
2636 type = xmlSchemaAddType(ctxt, schema, name, NULL);
2637 if (type == NULL)
2638 return (NULL);
2639 type->node = node;
2640 type->type = XML_SCHEMA_TYPE_LIST;
2641 type->id = xmlSchemaGetProp(ctxt, node, "id");
2642 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2643
2644 child = node->children;
2645 if (IS_SCHEMA(child, "annotation")) {
2646 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2647 child = child->next;
2648 }
2649
2650 subtype = NULL;
2651 if (IS_SCHEMA(child, "simpleType")) {
2652 subtype = (xmlSchemaTypePtr)
2653 xmlSchemaParseSimpleType(ctxt, schema, child);
2654 child = child->next;
2655 type->subtypes = subtype;
2656 }
2657 if (child != NULL) {
2658 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2659 "List %s has unexpected content\n", type->name,
2660 NULL);
2661 }
2662 return (type);
2663 }
2664
2665 /**
2666 * xmlSchemaParseSimpleType:
2667 * @param ctxt a schema validation context
2668 * @param schema the schema being built
2669 * @param node a subtree containing XML Schema informations
2670 *
2671 * parse a XML schema Simple Type definition
2672 * *WARNING* this interface is highly subject to change
2673 *
2674 * Returns -1 in case of error, 0 if the declaration is improper and
2675 * 1 in case of success.
2676 */
2677 static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2678 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2679 xmlNodePtr node)
2680 {
2681 xmlSchemaTypePtr type, subtype;
2682 xmlNodePtr child = NULL;
2683 const xmlChar *name;
2684
2685 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2686 return (NULL);
2687
2688
2689 name = xmlSchemaGetProp(ctxt, node, "name");
2690 if (name == NULL) {
2691 char buf[100];
2692
2693 snprintf(buf, 99, "simpleType %d", ctxt->counter++ + 1);
2694 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
2695 } else {
2696 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2697 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
2698 }
2699 if (type == NULL)
2700 return (NULL);
2701 type->node = node;
2702 type->type = XML_SCHEMA_TYPE_SIMPLE;
2703 type->id = xmlSchemaGetProp(ctxt, node, "id");
2704
2705 child = node->children;
2706 if (IS_SCHEMA(child, "annotation")) {
2707 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2708 child = child->next;
2709 }
2710 subtype = NULL;
2711 if (IS_SCHEMA(child, "restriction")) {
2712 subtype = (xmlSchemaTypePtr)
2713 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2714 child = child->next;
2715 } else if (IS_SCHEMA(child, "list")) {
2716 subtype = (xmlSchemaTypePtr)
2717 xmlSchemaParseList(ctxt, schema, child);
2718 child = child->next;
2719 } else if (IS_SCHEMA(child, "union")) {
2720 subtype = (xmlSchemaTypePtr)
2721 xmlSchemaParseUnion(ctxt, schema, child);
2722 child = child->next;
2723 }
2724 type->subtypes = subtype;
2725 if (subtype == NULL) {
2726 xmlSchemaPErr2(ctxt, node, child,
2727 XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD,
2728 "SimpleType %s does not define a variety\n",
2729 type->name, NULL);
2730 }
2731 if (child != NULL) {
2732 xmlSchemaPErr2(ctxt, node, child,
2733 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2734 "SimpleType %s has unexpected content\n",
2735 type->name, NULL);
2736 }
2737
2738 return (type);
2739 }
2740
2741
2742 /**
2743 * xmlSchemaParseGroup:
2744 * @param ctxt a schema validation context
2745 * @param schema the schema being built
2746 * @param node a subtree containing XML Schema informations
2747 *
2748 * parse a XML schema Group definition
2749 * *WARNING* this interface is highly subject to change
2750 *
2751 * Returns -1 in case of error, 0 if the declaration is improper and
2752 * 1 in case of success.
2753 */
2754 static xmlSchemaTypePtr
xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2755 xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2756 xmlNodePtr node)
2757 {
2758 xmlSchemaTypePtr type, subtype;
2759 xmlNodePtr child = NULL;
2760 const xmlChar *name;
2761 const xmlChar *ref = NULL, *refNs = NULL;
2762 char buf[100];
2763
2764 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2765 return (NULL);
2766
2767
2768 name = xmlSchemaGetProp(ctxt, node, "name");
2769 if (name == NULL) {
2770
2771 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2772 if (ref == NULL) {
2773 xmlSchemaPErr2(ctxt, node, child,
2774 XML_SCHEMAP_GROUP_NONAME_NOREF,
2775 "Group has no name nor ref\n", NULL, NULL);
2776 return (NULL);
2777 }
2778 if (refNs == NULL)
2779 refNs = schema->targetNamespace;
2780 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2781 name = (const xmlChar *) buf;
2782 }
2783 type = xmlSchemaAddGroup(ctxt, schema, name);
2784 if (type == NULL)
2785 return (NULL);
2786
2787 type->node = node;
2788 type->type = XML_SCHEMA_TYPE_GROUP;
2789 type->id = xmlSchemaGetProp(ctxt, node, "id");
2790 type->ref = ref;
2791 type->refNs = refNs;
2792 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2793 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2794
2795 child = node->children;
2796 if (IS_SCHEMA(child, "annotation")) {
2797 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2798 child = child->next;
2799 }
2800 subtype = NULL;
2801 if (IS_SCHEMA(child, "all")) {
2802 subtype = (xmlSchemaTypePtr)
2803 xmlSchemaParseAll(ctxt, schema, child);
2804 child = child->next;
2805 } else if (IS_SCHEMA(child, "choice")) {
2806 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2807 child = child->next;
2808 } else if (IS_SCHEMA(child, "sequence")) {
2809 subtype = (xmlSchemaTypePtr)
2810 xmlSchemaParseSequence(ctxt, schema, child);
2811 child = child->next;
2812 }
2813 if (subtype != NULL)
2814 type->subtypes = subtype;
2815 if (child != NULL) {
2816 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2817 "Group %s has unexpected content\n", type->name,
2818 NULL);
2819 }
2820
2821 return (type);
2822 }
2823
2824 /**
2825 * xmlSchemaParseAll:
2826 * @param ctxt a schema validation context
2827 * @param schema the schema being built
2828 * @param node a subtree containing XML Schema informations
2829 *
2830 * parse a XML schema All definition
2831 * *WARNING* this interface is highly subject to change
2832 *
2833 * Returns -1 in case of error, 0 if the declaration is improper and
2834 * 1 in case of success.
2835 */
2836 static xmlSchemaTypePtr
xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2837 xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2838 xmlNodePtr node)
2839 {
2840 xmlSchemaTypePtr type, subtype, last = NULL;
2841 xmlNodePtr child = NULL;
2842 xmlChar name[30];
2843
2844 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2845 return (NULL);
2846
2847
2848 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
2849 type = xmlSchemaAddType(ctxt, schema, name, NULL);
2850 if (type == NULL)
2851 return (NULL);
2852 type->node = node;
2853 type->type = XML_SCHEMA_TYPE_ALL;
2854 type->id = xmlSchemaGetProp(ctxt, node, "id");
2855 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2856 if (type->minOccurs > 1)
2857 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2858 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
2859 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2860 if (type->maxOccurs > 1)
2861 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2862 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
2863
2864 child = node->children;
2865 if (IS_SCHEMA(child, "annotation")) {
2866 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2867 child = child->next;
2868 }
2869 while (IS_SCHEMA(child, "element")) {
2870 subtype = (xmlSchemaTypePtr)
2871 xmlSchemaParseElement(ctxt, schema, child, 0);
2872 if (subtype != NULL) {
2873 if (subtype->minOccurs > 1)
2874 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
2875 "invalid value for minOccurs (must be 0 or 1)\n",
2876 NULL, NULL);
2877 if (subtype->maxOccurs > 1)
2878 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
2879 "invalid value for maxOccurs (must be 0 or 1)\n",
2880 NULL, NULL);
2881 if (last == NULL) {
2882 type->subtypes = subtype;
2883 last = subtype;
2884 } else {
2885 last->next = subtype;
2886 last = subtype;
2887 }
2888 last->next = NULL;
2889 }
2890 child = child->next;
2891 }
2892 if (child != NULL) {
2893 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2894 "All %s has unexpected content\n", type->name,
2895 NULL);
2896 }
2897
2898 return (type);
2899 }
2900
2901 /**
2902 * xmlSchemaImportSchema
2903 *
2904 * @param ctxt a schema validation context
2905 * @param schemaLocation an URI defining where to find the imported schema
2906 *
2907 * import a XML schema
2908 * *WARNING* this interface is highly subject to change
2909 *
2910 * Returns -1 in case of error and 1 in case of success.
2911 */
2912 static xmlSchemaImportPtr
xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,const xmlChar * schemaLocation)2913 xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2914 const xmlChar *schemaLocation)
2915 {
2916 xmlSchemaImportPtr import;
2917 xmlSchemaParserCtxtPtr newctxt;
2918
2919 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
2920 if (newctxt == NULL) {
2921 xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
2922 NULL);
2923 return (NULL);
2924 }
2925 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
2926 /* Keep the same dictionnary for parsing, really */
2927 xmlDictReference(ctxt->dict);
2928 newctxt->dict = ctxt->dict;
2929 newctxt->includes = 0;
2930 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
2931
2932 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2933 ctxt->userData);
2934
2935 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2936 if (import == NULL) {
2937 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2938 NULL);
2939 xmlSchemaFreeParserCtxt(newctxt);
2940 return (NULL);
2941 }
2942
2943 memset(import, 0, sizeof(xmlSchemaImport));
2944 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
2945 import->schema = xmlSchemaParse(newctxt);
2946
2947 if (import->schema == NULL) {
2948
2949 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2950 "failed to import schema at location %s\n",
2951 schemaLocation, NULL);
2952
2953 xmlSchemaFreeParserCtxt(newctxt);
2954 if (import->schemaLocation != NULL)
2955 xmlFree((xmlChar *)import->schemaLocation);
2956 xmlFree(import);
2957 return NULL;
2958 }
2959
2960 xmlSchemaFreeParserCtxt(newctxt);
2961 return import;
2962 }
2963
2964
2965 /**
2966 * xmlSchemaParseImport:
2967 * @param ctxt a schema validation context
2968 * @param schema the schema being built
2969 * @param node a subtree containing XML Schema informations
2970 *
2971 * parse a XML schema Import definition
2972 * *WARNING* this interface is highly subject to change
2973 *
2974 * Returns -1 in case of error, 0 if the declaration is improper and
2975 * 1 in case of success.
2976 */
2977 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)2978 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2979 xmlNodePtr node)
2980 {
2981 xmlNodePtr child = NULL;
2982 xmlSchemaImportPtr import = NULL;
2983 const xmlChar *namespace;
2984 const xmlChar *schemaLocation;
2985 const xmlChar *previous;
2986 xmlURIPtr check;
2987
2988
2989 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2990 return (-1);
2991
2992 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
2993 if (namespace != NULL) {
2994 check = xmlParseURI((const char *) namespace);
2995 if (check == NULL) {
2996 xmlSchemaPErr2(ctxt, node, child,
2997 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2998 "Import namespace attribute is not an URI: %s\n",
2999 namespace, NULL);
3000 return (-1);
3001 } else {
3002 xmlFreeURI(check);
3003 }
3004 }
3005 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
3006 if (schemaLocation != NULL) {
3007 xmlChar *base = NULL;
3008 xmlChar *URI = NULL;
3009 check = xmlParseURI((const char *) schemaLocation);
3010 if (check == NULL) {
3011 xmlSchemaPErr2(ctxt, node, child,
3012 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
3013 "Import schemaLocation attribute is not an URI: %s\n",
3014 schemaLocation, NULL);
3015 return (-1);
3016 } else {
3017 xmlFreeURI(check);
3018 }
3019 base = xmlNodeGetBase(node->doc, node);
3020 if (base == NULL) {
3021 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3022 } else {
3023 URI = xmlBuildURI(schemaLocation, base);
3024 xmlFree(base);
3025 }
3026 if (URI != NULL) {
3027 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3028 xmlFree(URI);
3029 }
3030 }
3031 if (schema->schemasImports == NULL) {
3032 schema->schemasImports = xmlHashCreate(10);
3033 if (schema->schemasImports == NULL) {
3034 xmlSchemaPErr2(ctxt, node, child,
3035 XML_SCHEMAP_FAILED_BUILD_IMPORT,
3036 "Internal: failed to build import table\n",
3037 NULL, NULL);
3038 return (-1);
3039 }
3040 }
3041 if (namespace == NULL) {
3042 import = xmlHashLookup(schema->schemasImports,
3043 XML_SCHEMAS_DEFAULT_NAMESPACE);
3044 if (import != NULL)
3045 previous = import->schemaLocation;
3046 else
3047 previous = NULL;
3048
3049 if (schemaLocation != NULL) {
3050 if (previous != NULL) {
3051 if (!xmlStrEqual(schemaLocation, previous)) {
3052 xmlSchemaPErr2(ctxt, node, child,
3053 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
3054 "Redefining import for default namespace "
3055 "with a different URI: %s\n",
3056 schemaLocation, NULL);
3057 }
3058 } else {
3059 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3060 if (import == NULL) {
3061 return (-1);
3062 }
3063 xmlHashAddEntry(schema->schemasImports,
3064 XML_SCHEMAS_DEFAULT_NAMESPACE,
3065 import);
3066 }
3067 }
3068 } else {
3069 import = xmlHashLookup(schema->schemasImports, namespace);
3070 if (import != NULL)
3071 previous = import->schemaLocation;
3072 else
3073 previous = NULL;
3074
3075 if (schemaLocation != NULL) {
3076 if (previous != NULL) {
3077 if (!xmlStrEqual(schemaLocation, previous)) {
3078 xmlSchemaPErr2(ctxt, node, child,
3079 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
3080 "Redefining import for namespace %s with "
3081 "a different URI: %s\n",
3082 namespace, schemaLocation);
3083 }
3084 } else {
3085 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3086 if (import == NULL) {
3087 return (-1);
3088 }
3089 xmlHashAddEntry(schema->schemasImports,
3090 namespace, import);
3091 }
3092 }
3093 }
3094
3095 child = node->children;
3096 while (IS_SCHEMA(child, "annotation")) {
3097 /*
3098 * the annotations here are simply discarded ...
3099 */
3100 child = child->next;
3101 }
3102 if (child != NULL) {
3103 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
3104 "Import has unexpected content\n", NULL, NULL);
3105 return (-1);
3106 }
3107 return (1);
3108 }
3109
3110 /**
3111 * xmlSchemaCleanupDoc:
3112 * @param ctxt a schema validation context
3113 * @param node the root of the document.
3114 *
3115 * removes unwanted nodes in a schemas document tree
3116 */
3117 static void
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr root)3118 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
3119 {
3120 xmlNodePtr delete, cur;
3121
3122 if ((ctxt == NULL) || (root == NULL)) return;
3123
3124 /*
3125 * Remove all the blank text nodes
3126 */
3127 delete = NULL;
3128 cur = root;
3129 while (cur != NULL) {
3130 if (delete != NULL) {
3131 xmlUnlinkNode(delete);
3132 xmlFreeNode(delete);
3133 delete = NULL;
3134 }
3135 if (cur->type == XML_TEXT_NODE) {
3136 if (IS_BLANK_NODE(cur)) {
3137 if (xmlNodeGetSpacePreserve(cur) != 1) {
3138 delete = cur;
3139 }
3140 }
3141 } else if ((cur->type != XML_ELEMENT_NODE) &&
3142 (cur->type != XML_CDATA_SECTION_NODE)) {
3143 delete = cur;
3144 goto skip_children;
3145 }
3146
3147 /*
3148 * Skip to next node
3149 */
3150 if (cur->children != NULL) {
3151 if ((cur->children->type != XML_ENTITY_DECL) &&
3152 (cur->children->type != XML_ENTITY_REF_NODE) &&
3153 (cur->children->type != XML_ENTITY_NODE)) {
3154 cur = cur->children;
3155 continue;
3156 }
3157 }
3158 skip_children:
3159 if (cur->next != NULL) {
3160 cur = cur->next;
3161 continue;
3162 }
3163
3164 do {
3165 cur = cur->parent;
3166 if (cur == NULL)
3167 break;
3168 if (cur == root) {
3169 cur = NULL;
3170 break;
3171 }
3172 if (cur->next != NULL) {
3173 cur = cur->next;
3174 break;
3175 }
3176 } while (cur != NULL);
3177 }
3178 if (delete != NULL) {
3179 xmlUnlinkNode(delete);
3180 xmlFreeNode(delete);
3181 delete = NULL;
3182 }
3183 }
3184
3185 /**
3186 * xmlSchemaParseSchemaTopLevel:
3187 * @param ctxt a schema validation context
3188 * @param schema the schemas
3189 * @param nodes the list of top level nodes
3190 *
3191 * Returns the internal XML Schema structure built from the resource or
3192 * NULL in case of error
3193 */
3194 static void
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr nodes)3195 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
3196 xmlSchemaPtr schema, xmlNodePtr nodes)
3197 {
3198 xmlNodePtr child;
3199 xmlSchemaAnnotPtr annot;
3200
3201 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
3202 return;
3203
3204 child = nodes;
3205 while ((IS_SCHEMA(child, "include")) ||
3206 (IS_SCHEMA(child, "import")) ||
3207 (IS_SCHEMA(child, "redefine")) ||
3208 (IS_SCHEMA(child, "annotation"))) {
3209 if (IS_SCHEMA(child, "annotation")) {
3210 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3211 if (schema->annot == NULL)
3212 schema->annot = annot;
3213 else
3214 xmlSchemaFreeAnnot(annot);
3215 } else if (IS_SCHEMA(child, "import")) {
3216 xmlSchemaParseImport(ctxt, schema, child);
3217 } else if (IS_SCHEMA(child, "include")) {
3218 ctxt->includes++;
3219 xmlSchemaParseInclude(ctxt, schema, child);
3220 ctxt->includes--;
3221 } else if (IS_SCHEMA(child, "redefine")) {
3222 TODO
3223 }
3224 child = child->next;
3225 }
3226 while (child != NULL) {
3227 if (IS_SCHEMA(child, "complexType")) {
3228 xmlSchemaParseComplexType(ctxt, schema, child);
3229 child = child->next;
3230 } else if (IS_SCHEMA(child, "simpleType")) {
3231 xmlSchemaParseSimpleType(ctxt, schema, child);
3232 child = child->next;
3233 } else if (IS_SCHEMA(child, "element")) {
3234 xmlSchemaParseElement(ctxt, schema, child, 1);
3235 child = child->next;
3236 } else if (IS_SCHEMA(child, "attribute")) {
3237 xmlSchemaParseAttribute(ctxt, schema, child, 1);
3238 child = child->next;
3239 } else if (IS_SCHEMA(child, "attributeGroup")) {
3240 xmlSchemaParseAttributeGroup(ctxt, schema, child);
3241 child = child->next;
3242 } else if (IS_SCHEMA(child, "group")) {
3243 xmlSchemaParseGroup(ctxt, schema, child);
3244 child = child->next;
3245 } else if (IS_SCHEMA(child, "notation")) {
3246 xmlSchemaParseNotation(ctxt, schema, child);
3247 child = child->next;
3248 } else {
3249 xmlSchemaPErr2(ctxt, NULL, child,
3250 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3251 "Schemas: unexpected element %s here \n",
3252 child->name, NULL);
3253 child = child->next;
3254 }
3255 while (IS_SCHEMA(child, "annotation")) {
3256 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3257 if (schema->annot == NULL)
3258 schema->annot = annot;
3259 else
3260 xmlSchemaFreeAnnot(annot);
3261 child = child->next;
3262 }
3263 }
3264 }
3265
3266 /**
3267 * xmlSchemaParseInclude:
3268 * @param ctxt a schema validation context
3269 * @param schema the schema being built
3270 * @param node a subtree containing XML Schema informations
3271 *
3272 * parse a XML schema Include definition
3273 *
3274 * Returns -1 in case of error, 0 if the declaration is improper and
3275 * 1 in case of success.
3276 */
3277 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3278 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3279 xmlNodePtr node)
3280 {
3281 xmlNodePtr child = NULL;
3282 const xmlChar *schemaLocation;
3283 xmlURIPtr check;
3284 xmlDocPtr doc;
3285 xmlNodePtr root;
3286 xmlSchemaIncludePtr include;
3287
3288
3289 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3290 return (-1);
3291
3292 /*
3293 * Preliminary step, extract the URI-Reference for the include and
3294 * make an URI from the base.
3295 */
3296 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
3297 if (schemaLocation != NULL) {
3298 xmlChar *base = NULL;
3299 xmlChar *URI = NULL;
3300 check = xmlParseURI((const char *) schemaLocation);
3301 if (check == NULL) {
3302 xmlSchemaPErr2(ctxt, node, child,
3303 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3304 "Include schemaLocation attribute is not an URI: %s\n",
3305 schemaLocation, NULL);
3306 return (-1);
3307 } else {
3308 xmlFreeURI(check);
3309 }
3310 base = xmlNodeGetBase(node->doc, node);
3311 if (base == NULL) {
3312 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3313 } else {
3314 URI = xmlBuildURI(schemaLocation, base);
3315 xmlFree(base);
3316 }
3317 if (URI != NULL) {
3318 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3319 xmlFree(URI);
3320 }
3321 } else {
3322 xmlSchemaPErr2(ctxt, node, child,
3323 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3324 "Include schemaLocation attribute missing\n",
3325 NULL, NULL);
3326 return (-1);
3327 }
3328
3329 child = node->children;
3330 while (IS_SCHEMA(child, "annotation")) {
3331 /*
3332 * the annotations here are simply discarded ...
3333 */
3334 child = child->next;
3335 }
3336 if (child != NULL) {
3337 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3338 "Include has unexpected content\n", NULL, NULL);
3339 return (-1);
3340 }
3341
3342 /*
3343 * First step is to parse the input document into an DOM/Infoset
3344 */
3345 doc = xmlReadFile((const char *) schemaLocation, NULL,
3346 SCHEMAS_PARSE_OPTIONS);
3347 if (doc == NULL) {
3348 xmlSchemaPErr(ctxt, NULL,
3349 XML_SCHEMAP_FAILED_LOAD,
3350 "xmlSchemaParse: could not load %s\n",
3351 ctxt->URL, NULL);
3352 return(-1);
3353 }
3354
3355 /*
3356 * Then extract the root of the schema
3357 */
3358 root = xmlDocGetRootElement(doc);
3359 if (root == NULL) {
3360 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3361 XML_SCHEMAP_NOROOT,
3362 "schemas %s has no root", schemaLocation, NULL);
3363 xmlFreeDoc(doc);
3364 return (-1);
3365 }
3366
3367 /*
3368 * Remove all the blank text nodes
3369 */
3370 xmlSchemaCleanupDoc(ctxt, root);
3371
3372 /*
3373 * Check the schemas top level element
3374 */
3375 if (!IS_SCHEMA(root, "schema")) {
3376 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3377 XML_SCHEMAP_NOT_SCHEMA,
3378 "File %s is not a schemas", schemaLocation, NULL);
3379 xmlFreeDoc(doc);
3380 return (-1);
3381 }
3382
3383 /*
3384 * register the include
3385 */
3386 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3387 if (include == NULL) {
3388 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3389 xmlFreeDoc(doc);
3390 return (-1);
3391 }
3392
3393 memset(include, 0, sizeof(xmlSchemaInclude));
3394 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3395 include->doc = doc;
3396 include->next = schema->includes;
3397 schema->includes = include;
3398
3399
3400 /*
3401 * parse the declarations in the included file like if they
3402 * were in the original file.
3403 */
3404 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3405
3406 return (1);
3407 }
3408
3409 /**
3410 * xmlSchemaParseChoice:
3411 * @param ctxt a schema validation context
3412 * @param schema the schema being built
3413 * @param node a subtree containing XML Schema informations
3414 *
3415 * parse a XML schema Choice definition
3416 * *WARNING* this interface is highly subject to change
3417 *
3418 * Returns -1 in case of error, 0 if the declaration is improper and
3419 * 1 in case of success.
3420 */
3421 static xmlSchemaTypePtr
xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3422 xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3423 xmlNodePtr node)
3424 {
3425 xmlSchemaTypePtr type, subtype, last = NULL;
3426 xmlNodePtr child = NULL;
3427 xmlChar name[30];
3428
3429 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3430 return (NULL);
3431
3432
3433 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
3434 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3435 if (type == NULL)
3436 return (NULL);
3437 type->node = node;
3438 type->type = XML_SCHEMA_TYPE_CHOICE;
3439 type->id = xmlSchemaGetProp(ctxt, node, "id");
3440 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3441 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3442
3443 child = node->children;
3444 if (IS_SCHEMA(child, "annotation")) {
3445 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3446 child = child->next;
3447 }
3448 while ((IS_SCHEMA(child, "element")) ||
3449 (IS_SCHEMA(child, "group")) ||
3450 (IS_SCHEMA(child, "any")) ||
3451 (IS_SCHEMA(child, "choice")) ||
3452 (IS_SCHEMA(child, "sequence"))) {
3453 subtype = NULL;
3454 if (IS_SCHEMA(child, "element")) {
3455 subtype = (xmlSchemaTypePtr)
3456 xmlSchemaParseElement(ctxt, schema, child, 0);
3457 } else if (IS_SCHEMA(child, "group")) {
3458 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3459 } else if (IS_SCHEMA(child, "any")) {
3460 subtype = xmlSchemaParseAny(ctxt, schema, child);
3461 } else if (IS_SCHEMA(child, "sequence")) {
3462 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3463 } else if (IS_SCHEMA(child, "choice")) {
3464 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3465 }
3466 if (subtype != NULL) {
3467 if (last == NULL) {
3468 type->subtypes = subtype;
3469 last = subtype;
3470 } else {
3471 last->next = subtype;
3472 last = subtype;
3473 }
3474 last->next = NULL;
3475 }
3476 child = child->next;
3477 }
3478 if (child != NULL) {
3479 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3480 "Choice %s has unexpected content\n", type->name,
3481 NULL);
3482 }
3483
3484 return (type);
3485 }
3486
3487 /**
3488 * xmlSchemaParseSequence:
3489 * @param ctxt a schema validation context
3490 * @param schema the schema being built
3491 * @param node a subtree containing XML Schema informations
3492 *
3493 * parse a XML schema Sequence definition
3494 * *WARNING* this interface is highly subject to change
3495 *
3496 * Returns -1 in case of error, 0 if the declaration is improper and
3497 * 1 in case of success.
3498 */
3499 static xmlSchemaTypePtr
xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3500 xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3501 xmlNodePtr node)
3502 {
3503 xmlSchemaTypePtr type, subtype, last = NULL;
3504 xmlNodePtr child = NULL;
3505 xmlChar name[30];
3506
3507 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3508 return (NULL);
3509
3510
3511 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
3512 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3513 if (type == NULL)
3514 return (NULL);
3515 type->node = node;
3516 type->type = XML_SCHEMA_TYPE_SEQUENCE;
3517 type->id = xmlSchemaGetProp(ctxt, node, "id");
3518 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3519 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3520
3521 child = node->children;
3522 if (IS_SCHEMA(child, "annotation")) {
3523 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3524 child = child->next;
3525 }
3526 while ((IS_SCHEMA(child, "element")) ||
3527 (IS_SCHEMA(child, "group")) ||
3528 (IS_SCHEMA(child, "any")) ||
3529 (IS_SCHEMA(child, "choice")) ||
3530 (IS_SCHEMA(child, "sequence"))) {
3531 subtype = NULL;
3532 if (IS_SCHEMA(child, "element")) {
3533 subtype = (xmlSchemaTypePtr)
3534 xmlSchemaParseElement(ctxt, schema, child, 0);
3535 } else if (IS_SCHEMA(child, "group")) {
3536 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3537 } else if (IS_SCHEMA(child, "any")) {
3538 subtype = xmlSchemaParseAny(ctxt, schema, child);
3539 } else if (IS_SCHEMA(child, "choice")) {
3540 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3541 } else if (IS_SCHEMA(child, "sequence")) {
3542 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3543 }
3544 if (subtype != NULL) {
3545 if (last == NULL) {
3546 type->subtypes = subtype;
3547 last = subtype;
3548 } else {
3549 last->next = subtype;
3550 last = subtype;
3551 }
3552 last->next = NULL;
3553 }
3554 child = child->next;
3555 }
3556 if (child != NULL) {
3557 xmlSchemaPErr2(ctxt, node, child,
3558 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3559 "Sequence %s has unexpected content\n", type->name,
3560 NULL);
3561 }
3562
3563 return (type);
3564 }
3565
3566 /**
3567 * xmlSchemaParseRestriction:
3568 * @param ctxt a schema validation context
3569 * @param schema the schema being built
3570 * @param node a subtree containing XML Schema informations
3571 * @param simple is that part of a simple type.
3572 *
3573 * parse a XML schema Restriction definition
3574 * *WARNING* this interface is highly subject to change
3575 *
3576 * Returns the type definition or NULL in case of error
3577 */
3578 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int simple)3579 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3580 xmlNodePtr node, int simple)
3581 {
3582 xmlSchemaTypePtr type, subtype;
3583 xmlSchemaFacetPtr facet, lastfacet = NULL;
3584 xmlNodePtr child = NULL;
3585 xmlChar name[30];
3586 const xmlChar *oldcontainer;
3587
3588 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3589 return (NULL);
3590
3591 oldcontainer = ctxt->container;
3592
3593 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
3594 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3595 if (type == NULL)
3596 return (NULL);
3597 type->node = node;
3598 type->type = XML_SCHEMA_TYPE_RESTRICTION;
3599 type->id = xmlSchemaGetProp(ctxt, node, "id");
3600 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3601 if ((!simple) && (type->base == NULL)) {
3602 xmlSchemaPErr2(ctxt, node, child,
3603 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
3604 "Restriction %s has no base\n", type->name, NULL);
3605 }
3606 ctxt->container = name;
3607
3608 child = node->children;
3609 if (IS_SCHEMA(child, "annotation")) {
3610 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3611 child = child->next;
3612 }
3613 subtype = NULL;
3614
3615 if (IS_SCHEMA(child, "all")) {
3616 subtype = (xmlSchemaTypePtr)
3617 xmlSchemaParseAll(ctxt, schema, child);
3618 child = child->next;
3619 type->subtypes = subtype;
3620 } else if (IS_SCHEMA(child, "choice")) {
3621 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3622 child = child->next;
3623 type->subtypes = subtype;
3624 } else if (IS_SCHEMA(child, "sequence")) {
3625 subtype = (xmlSchemaTypePtr)
3626 xmlSchemaParseSequence(ctxt, schema, child);
3627 child = child->next;
3628 type->subtypes = subtype;
3629 } else if (IS_SCHEMA(child, "group")) {
3630 subtype = (xmlSchemaTypePtr)
3631 xmlSchemaParseGroup(ctxt, schema, child);
3632 child = child->next;
3633 type->subtypes = subtype;
3634 } else {
3635 if (IS_SCHEMA(child, "simpleType")) {
3636 subtype = (xmlSchemaTypePtr)
3637 xmlSchemaParseSimpleType(ctxt, schema, child);
3638 child = child->next;
3639 type->baseType = subtype;
3640 }
3641 /*
3642 * Facets
3643 */
3644 while ((IS_SCHEMA(child, "minInclusive")) ||
3645 (IS_SCHEMA(child, "minExclusive")) ||
3646 (IS_SCHEMA(child, "maxInclusive")) ||
3647 (IS_SCHEMA(child, "maxExclusive")) ||
3648 (IS_SCHEMA(child, "totalDigits")) ||
3649 (IS_SCHEMA(child, "fractionDigits")) ||
3650 (IS_SCHEMA(child, "pattern")) ||
3651 (IS_SCHEMA(child, "enumeration")) ||
3652 (IS_SCHEMA(child, "whiteSpace")) ||
3653 (IS_SCHEMA(child, "length")) ||
3654 (IS_SCHEMA(child, "maxLength")) ||
3655 (IS_SCHEMA(child, "minLength"))) {
3656 facet = xmlSchemaParseFacet(ctxt, schema, child);
3657 if (facet != NULL) {
3658 if (lastfacet == NULL) {
3659 type->facets = facet;
3660 lastfacet = facet;
3661 } else {
3662 lastfacet->next = facet;
3663 lastfacet = facet;
3664 }
3665 lastfacet->next = NULL;
3666 }
3667 child = child->next;
3668 }
3669 }
3670 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3671 if (child != NULL) {
3672 xmlSchemaPErr2(ctxt, node, child,
3673 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
3674 "Restriction %s has unexpected content\n",
3675 type->name, NULL);
3676 }
3677 ctxt->container = oldcontainer;
3678 return (type);
3679 }
3680
3681 /**
3682 * xmlSchemaParseExtension:
3683 * @param ctxt a schema validation context
3684 * @param schema the schema being built
3685 * @param node a subtree containing XML Schema informations
3686 *
3687 * parse a XML schema Extension definition
3688 * *WARNING* this interface is highly subject to change
3689 *
3690 * Returns the type definition or NULL in case of error
3691 */
3692 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3693 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3694 xmlNodePtr node)
3695 {
3696 xmlSchemaTypePtr type, subtype;
3697 xmlNodePtr child = NULL;
3698 xmlChar name[30];
3699 const xmlChar *oldcontainer;
3700
3701 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3702 return (NULL);
3703
3704 oldcontainer = ctxt->container;
3705
3706 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
3707 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3708 if (type == NULL)
3709 return (NULL);
3710 type->node = node;
3711 type->type = XML_SCHEMA_TYPE_EXTENSION;
3712 type->id = xmlSchemaGetProp(ctxt, node, "id");
3713 ctxt->container = name;
3714
3715 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3716 if (type->base == NULL) {
3717 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3718 "Extension %s has no base\n", type->name, NULL);
3719 }
3720 child = node->children;
3721 if (IS_SCHEMA(child, "annotation")) {
3722 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3723 child = child->next;
3724 }
3725 subtype = NULL;
3726
3727 if (IS_SCHEMA(child, "all")) {
3728 subtype = xmlSchemaParseAll(ctxt, schema, child);
3729 child = child->next;
3730 } else if (IS_SCHEMA(child, "choice")) {
3731 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3732 child = child->next;
3733 } else if (IS_SCHEMA(child, "sequence")) {
3734 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3735 child = child->next;
3736 } else if (IS_SCHEMA(child, "group")) {
3737 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3738 child = child->next;
3739 }
3740 if (subtype != NULL)
3741 type->subtypes = subtype;
3742 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3743 if (child != NULL) {
3744 xmlSchemaPErr2(ctxt, node, child,
3745 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3746 "Extension %s has unexpected content\n", type->name,
3747 NULL);
3748 }
3749 ctxt->container = oldcontainer;
3750 return (type);
3751 }
3752
3753 /**
3754 * xmlSchemaParseSimpleContent:
3755 * @param ctxt a schema validation context
3756 * @param schema the schema being built
3757 * @param node a subtree containing XML Schema informations
3758 *
3759 * parse a XML schema SimpleContent definition
3760 * *WARNING* this interface is highly subject to change
3761 *
3762 * Returns the type definition or NULL in case of error
3763 */
3764 static xmlSchemaTypePtr
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3765 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3766 xmlSchemaPtr schema, xmlNodePtr node)
3767 {
3768 xmlSchemaTypePtr type, subtype;
3769 xmlNodePtr child = NULL;
3770 xmlChar name[30];
3771
3772 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3773 return (NULL);
3774
3775
3776 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
3777 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3778 if (type == NULL)
3779 return (NULL);
3780 type->node = node;
3781 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
3782 type->id = xmlSchemaGetProp(ctxt, node, "id");
3783
3784 child = node->children;
3785 if (IS_SCHEMA(child, "annotation")) {
3786 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3787 child = child->next;
3788 }
3789 subtype = NULL;
3790 if (IS_SCHEMA(child, "restriction")) {
3791 subtype = (xmlSchemaTypePtr)
3792 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3793 child = child->next;
3794 } else if (IS_SCHEMA(child, "extension")) {
3795 subtype = (xmlSchemaTypePtr)
3796 xmlSchemaParseExtension(ctxt, schema, child);
3797 child = child->next;
3798 }
3799 type->subtypes = subtype;
3800 if (child != NULL) {
3801 xmlSchemaPErr2(ctxt, node, child,
3802 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3803 "SimpleContent %s has unexpected content\n",
3804 type->name, NULL);
3805 }
3806 return (type);
3807 }
3808
3809 /**
3810 * xmlSchemaParseComplexContent:
3811 * @param ctxt a schema validation context
3812 * @param schema the schema being built
3813 * @param node a subtree containing XML Schema informations
3814 *
3815 * parse a XML schema ComplexContent definition
3816 * *WARNING* this interface is highly subject to change
3817 *
3818 * Returns the type definition or NULL in case of error
3819 */
3820 static xmlSchemaTypePtr
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3821 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3822 xmlSchemaPtr schema, xmlNodePtr node)
3823 {
3824 xmlSchemaTypePtr type, subtype;
3825 xmlNodePtr child = NULL;
3826 xmlChar name[30];
3827
3828 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3829 return (NULL);
3830
3831
3832 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
3833 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3834 if (type == NULL)
3835 return (NULL);
3836 type->node = node;
3837 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
3838 type->id = xmlSchemaGetProp(ctxt, node, "id");
3839
3840 child = node->children;
3841 if (IS_SCHEMA(child, "annotation")) {
3842 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3843 child = child->next;
3844 }
3845 subtype = NULL;
3846 if (IS_SCHEMA(child, "restriction")) {
3847 subtype = (xmlSchemaTypePtr)
3848 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3849 child = child->next;
3850 } else if (IS_SCHEMA(child, "extension")) {
3851 subtype = (xmlSchemaTypePtr)
3852 xmlSchemaParseExtension(ctxt, schema, child);
3853 child = child->next;
3854 }
3855 type->subtypes = subtype;
3856 if (child != NULL) {
3857 xmlSchemaPErr2(ctxt, node, child,
3858 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3859 "ComplexContent %s has unexpected content\n",
3860 type->name, NULL);
3861 }
3862 return (type);
3863 }
3864
3865 /**
3866 * xmlSchemaParseComplexType:
3867 * @param ctxt a schema validation context
3868 * @param schema the schema being built
3869 * @param node a subtree containing XML Schema informations
3870 *
3871 * parse a XML schema Complex Type definition
3872 * *WARNING* this interface is highly subject to change
3873 *
3874 * Returns the type definition or NULL in case of error
3875 */
3876 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)3877 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3878 xmlNodePtr node)
3879 {
3880 xmlSchemaTypePtr type, subtype;
3881 xmlNodePtr child = NULL;
3882 const xmlChar *name;
3883 const xmlChar *oldcontainer;
3884 char buf[100];
3885
3886 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3887 return (NULL);
3888
3889 oldcontainer = ctxt->container;
3890 name = xmlSchemaGetProp(ctxt, node, "name");
3891 if (name == NULL) {
3892
3893 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
3894 name = (const xmlChar *)buf;
3895 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3896 } else {
3897
3898 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
3899 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
3900 }
3901 if (type == NULL) {
3902 return (NULL);
3903 }
3904
3905 if (xmlGetBooleanProp(ctxt, node, "mixed", 0))
3906 type->flags |= XML_SCHEMAS_TYPE_MIXED;
3907
3908 type->node = node;
3909 type->type = XML_SCHEMA_TYPE_COMPLEX;
3910 type->id = xmlSchemaGetProp(ctxt, node, "id");
3911 ctxt->container = name;
3912
3913 child = node->children;
3914 if (IS_SCHEMA(child, "annotation")) {
3915 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3916 child = child->next;
3917 }
3918 if (IS_SCHEMA(child, "simpleContent")) {
3919 /* 3.4.3 : 2.2
3920 * Specifying mixed='true' when the <simpleContent>
3921 * alternative is chosen has no effect
3922 */
3923 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
3924 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
3925 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3926 child = child->next;
3927 } else if (IS_SCHEMA(child, "complexContent")) {
3928 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3929 child = child->next;
3930 } else {
3931 subtype = NULL;
3932
3933 if (IS_SCHEMA(child, "all")) {
3934 subtype = xmlSchemaParseAll(ctxt, schema, child);
3935 child = child->next;
3936 } else if (IS_SCHEMA(child, "choice")) {
3937 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3938 child = child->next;
3939 } else if (IS_SCHEMA(child, "sequence")) {
3940 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3941 child = child->next;
3942 } else if (IS_SCHEMA(child, "group")) {
3943 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3944 child = child->next;
3945 }
3946 if (subtype != NULL)
3947 type->subtypes = subtype;
3948 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3949 }
3950 if (child != NULL) {
3951 xmlSchemaPErr2(ctxt, node, child,
3952 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3953 "ComplexType %s has unexpected content\n",
3954 type->name, NULL);
3955 }
3956 ctxt->container = oldcontainer;
3957 return (type);
3958 }
3959
3960 /**
3961 * xmlSchemaParseSchema:
3962 * @param ctxt a schema validation context
3963 * @param node a subtree containing XML Schema informations
3964 *
3965 * parse a XML schema definition from a node set
3966 * *WARNING* this interface is highly subject to change
3967 *
3968 * Returns the internal XML Schema structure built from the resource or
3969 * NULL in case of error
3970 */
3971 static xmlSchemaPtr
xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)3972 xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3973 {
3974 xmlSchemaPtr schema = NULL;
3975 xmlNodePtr child = NULL;
3976 const xmlChar *val;
3977 int nberrors;
3978
3979 if ((ctxt == NULL) || (node == NULL))
3980 return (NULL);
3981
3982 nberrors = ctxt->nberrors;
3983 ctxt->nberrors = 0;
3984 if (IS_SCHEMA(node, "schema")) {
3985 schema = xmlSchemaNewSchema(ctxt);
3986 if (schema == NULL)
3987 return (NULL);
3988 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3989 if (val != NULL) {
3990 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3991 } else {
3992 schema->targetNamespace = NULL;
3993 }
3994 schema->id = xmlSchemaGetProp(ctxt, node, "id");
3995 schema->version = xmlSchemaGetProp(ctxt, node, "version");
3996 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
3997 if (val != NULL) {
3998 if (xmlStrEqual(val, BAD_CAST "qualified"))
3999 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
4000 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4001 xmlSchemaPErr2(ctxt, node, child,
4002 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
4003 "Invalid value %s for elementFormDefault\n",
4004 val, NULL);
4005 }
4006 } else {
4007 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
4008 }
4009 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
4010 if (val != NULL) {
4011 if (xmlStrEqual(val, BAD_CAST "qualified"))
4012 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
4013 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4014 xmlSchemaPErr2(ctxt, node, child,
4015 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
4016 "Invalid value %s for attributeFormDefault\n",
4017 val, NULL);
4018 }
4019 }
4020
4021 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
4022 } else {
4023 xmlDocPtr doc;
4024
4025 doc = node->doc;
4026
4027 if ((doc != NULL) && (doc->URL != NULL)) {
4028 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4029 XML_SCHEMAP_NOT_SCHEMA,
4030 "File %s is not a schemas", doc->URL, NULL);
4031 } else {
4032 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4033 XML_SCHEMAP_NOT_SCHEMA,
4034 "File is not a schemas", NULL, NULL);
4035 }
4036 return(NULL);
4037 }
4038 if (ctxt->nberrors != 0) {
4039 if (schema != NULL) {
4040 xmlSchemaFree(schema);
4041 schema = NULL;
4042 }
4043 }
4044 ctxt->nberrors = nberrors;
4045 #ifdef DEBUG
4046 if (schema == NULL)
4047 xmlGenericError(xmlGenericErrorContext,
4048 "xmlSchemaParse() failed\n");
4049 #endif
4050
4051 return (schema);
4052 }
4053
4054 /************************************************************************
4055 * *
4056 * Validating using Schemas *
4057 * *
4058 ************************************************************************/
4059
4060 /************************************************************************
4061 * *
4062 * Reading/Writing Schemas *
4063 * *
4064 ************************************************************************/
4065
4066 /**
4067 * xmlSchemaNewParserCtxt:
4068 * @param URL the location of the schema
4069 *
4070 * Create an XML Schemas parse context for that file/resource expected
4071 * to contain an XML Schemas file.
4072 *
4073 * Returns the parser context or NULL in case of error
4074 */
4075 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)4076 xmlSchemaNewParserCtxt(const char *URL)
4077 {
4078 xmlSchemaParserCtxtPtr ret;
4079
4080 if (URL == NULL)
4081 return (NULL);
4082
4083 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4084 if (ret == NULL) {
4085 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4086 NULL);
4087 return (NULL);
4088 }
4089 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4090 ret->dict = xmlDictCreate();
4091 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
4092 ret->includes = 0;
4093 return (ret);
4094 }
4095
4096 /**
4097 * xmlSchemaNewMemParserCtxt:
4098 * @param buffer a pointer to a char array containing the schemas
4099 * @param size the size of the array
4100 *
4101 * Create an XML Schemas parse context for that memory buffer expected
4102 * to contain an XML Schemas file.
4103 *
4104 * Returns the parser context or NULL in case of error
4105 */
4106 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)4107 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
4108 {
4109 xmlSchemaParserCtxtPtr ret;
4110
4111 if ((buffer == NULL) || (size <= 0))
4112 return (NULL);
4113
4114 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4115 if (ret == NULL) {
4116 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4117 NULL);
4118 return (NULL);
4119 }
4120 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4121 ret->buffer = buffer;
4122 ret->size = size;
4123 ret->dict = xmlDictCreate();
4124 return (ret);
4125 }
4126
4127 /**
4128 * xmlSchemaNewDocParserCtxt:
4129 * @param doc a preparsed document tree
4130 *
4131 * Create an XML Schemas parse context for that document.
4132 * NB. The document may be modified during the parsing process.
4133 *
4134 * Returns the parser context or NULL in case of error
4135 */
4136 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)4137 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
4138 {
4139 xmlSchemaParserCtxtPtr ret;
4140
4141 if (doc == NULL)
4142 return (NULL);
4143
4144 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4145 if (ret == NULL) {
4146 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
4147 NULL);
4148 return (NULL);
4149 }
4150 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4151 ret->doc = doc;
4152 ret->dict = xmlDictCreate();
4153 /* The application has responsibility for the document */
4154 ret->preserve = 1;
4155
4156 return (ret);
4157 }
4158
4159 /**
4160 * xmlSchemaFreeParserCtxt:
4161 * @param ctxt the schema parser context
4162 *
4163 * Free the resources associated to the schema parser context
4164 */
4165 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)4166 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
4167 {
4168 if (ctxt == NULL)
4169 return;
4170 if (ctxt->doc != NULL && !ctxt->preserve)
4171 xmlFreeDoc(ctxt->doc);
4172 xmlDictFree(ctxt->dict);
4173 xmlFree(ctxt);
4174 }
4175
4176 /************************************************************************
4177 * *
4178 * Building the content models *
4179 * *
4180 ************************************************************************/
4181
4182 /**
4183 * xmlSchemaBuildAContentModel:
4184 * @param type the schema type definition
4185 * @param ctxt the schema parser context
4186 * @param name the element name whose content is being built
4187 *
4188 * Generate the automata sequence needed for that type
4189 */
4190 static void
xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)4191 xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
4192 xmlSchemaParserCtxtPtr ctxt,
4193 const xmlChar * name)
4194 {
4195 if (type == NULL) {
4196 xmlGenericError(xmlGenericErrorContext,
4197 "Found unexpected type = NULL in %s content model\n",
4198 name);
4199 return;
4200 }
4201 switch (type->type) {
4202 case XML_SCHEMA_TYPE_ANY:
4203
4204
4205 TODO ctxt->state =
4206 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
4207 BAD_CAST "*", NULL);
4208 break;
4209 case XML_SCHEMA_TYPE_ELEMENT:{
4210 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4211
4212
4213 xmlAutomataStatePtr oldstate = ctxt->state;
4214
4215 if (elem->maxOccurs >= UNBOUNDED) {
4216 if (elem->minOccurs > 1) {
4217 xmlAutomataStatePtr tmp;
4218 int counter;
4219
4220 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4221 oldstate,
4222 NULL);
4223 oldstate = ctxt->state;
4224
4225 counter = xmlAutomataNewCounter(ctxt->am,
4226 elem->minOccurs -
4227 1, UNBOUNDED);
4228
4229 if (elem->refDecl != NULL) {
4230 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4231 elem->refDecl,
4232 ctxt,
4233 elem->refDecl->
4234 name);
4235 } else {
4236 ctxt->state =
4237 xmlAutomataNewTransition(ctxt->am,
4238 ctxt->state, NULL,
4239 elem->name, type);
4240 }
4241 tmp = ctxt->state;
4242 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4243 counter);
4244 ctxt->state =
4245 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4246 counter);
4247
4248 } else {
4249 if (elem->refDecl != NULL) {
4250 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4251 elem->refDecl,
4252 ctxt,
4253 elem->refDecl->
4254 name);
4255 } else {
4256 ctxt->state =
4257 xmlAutomataNewTransition(ctxt->am,
4258 ctxt->state, NULL,
4259 elem->name, type);
4260 }
4261 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4262 oldstate);
4263 if (elem->minOccurs == 0) {
4264 /* basically an elem* */
4265 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4266 ctxt->state);
4267 }
4268 }
4269 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
4270 xmlAutomataStatePtr tmp;
4271 int counter;
4272
4273 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4274 oldstate, NULL);
4275 oldstate = ctxt->state;
4276
4277 counter = xmlAutomataNewCounter(ctxt->am,
4278 elem->minOccurs - 1,
4279 elem->maxOccurs - 1);
4280
4281 if (elem->refDecl != NULL) {
4282 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4283 elem->refDecl, ctxt,
4284 elem->refDecl->name);
4285 } else {
4286 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4287 ctxt->state,
4288 NULL,
4289 elem->name,
4290 type);
4291 }
4292 tmp = ctxt->state;
4293 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4294 counter);
4295 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
4296 NULL,
4297 counter);
4298 if (elem->minOccurs == 0) {
4299 /* basically an elem? */
4300 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4301 ctxt->state);
4302 }
4303
4304 } else {
4305 if (elem->refDecl != NULL) {
4306 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4307 elem->refDecl, ctxt,
4308 elem->refDecl->name);
4309 } else {
4310 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4311 ctxt->state,
4312 NULL,
4313 elem->name,
4314 type);
4315 }
4316 if (elem->minOccurs == 0) {
4317 /* basically an elem? */
4318 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4319 ctxt->state);
4320 }
4321 }
4322 break;
4323 }
4324 case XML_SCHEMA_TYPE_SEQUENCE:{
4325 xmlSchemaTypePtr subtypes;
4326
4327 /*
4328 * If max and min occurances are default (1) then
4329 * simply iterate over the subtypes
4330 */
4331 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4332 subtypes = type->subtypes;
4333 while (subtypes != NULL) {
4334 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4335 subtypes = subtypes->next;
4336 }
4337 } else {
4338 xmlAutomataStatePtr oldstate = ctxt->state;
4339
4340 if (type->maxOccurs >= UNBOUNDED) {
4341 if (type->minOccurs > 1) {
4342 xmlAutomataStatePtr tmp;
4343 int counter;
4344
4345 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4346 oldstate,
4347 NULL);
4348 oldstate = ctxt->state;
4349
4350 counter = xmlAutomataNewCounter(ctxt->am,
4351 type->
4352 minOccurs - 1,
4353 UNBOUNDED);
4354
4355 subtypes = type->subtypes;
4356 while (subtypes != NULL) {
4357 xmlSchemaBuildAContentModel(subtypes, ctxt,
4358 name);
4359 subtypes = subtypes->next;
4360 }
4361 tmp = ctxt->state;
4362 xmlAutomataNewCountedTrans(ctxt->am, tmp,
4363 oldstate, counter);
4364 ctxt->state =
4365 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4366 NULL, counter);
4367
4368 } else {
4369 subtypes = type->subtypes;
4370 while (subtypes != NULL) {
4371 xmlSchemaBuildAContentModel(subtypes, ctxt,
4372 name);
4373 subtypes = subtypes->next;
4374 }
4375 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4376 oldstate);
4377 if (type->minOccurs == 0) {
4378 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4379 ctxt->state);
4380 }
4381 }
4382 } else if ((type->maxOccurs > 1)
4383 || (type->minOccurs > 1)) {
4384 xmlAutomataStatePtr tmp;
4385 int counter;
4386
4387 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4388 oldstate,
4389 NULL);
4390 oldstate = ctxt->state;
4391
4392 counter = xmlAutomataNewCounter(ctxt->am,
4393 type->minOccurs -
4394 1,
4395 type->maxOccurs -
4396 1);
4397
4398 subtypes = type->subtypes;
4399 while (subtypes != NULL) {
4400 xmlSchemaBuildAContentModel(subtypes, ctxt,
4401 name);
4402 subtypes = subtypes->next;
4403 }
4404 tmp = ctxt->state;
4405 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4406 counter);
4407 ctxt->state =
4408 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4409 counter);
4410 if (type->minOccurs == 0) {
4411 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4412 ctxt->state);
4413 }
4414
4415 } else {
4416 subtypes = type->subtypes;
4417 while (subtypes != NULL) {
4418 xmlSchemaBuildAContentModel(subtypes, ctxt,
4419 name);
4420 subtypes = subtypes->next;
4421 }
4422 if (type->minOccurs == 0) {
4423 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4424 ctxt->state);
4425 }
4426 }
4427 }
4428 break;
4429 }
4430 case XML_SCHEMA_TYPE_CHOICE:{
4431 xmlSchemaTypePtr subtypes;
4432 xmlAutomataStatePtr start, end;
4433
4434 start = ctxt->state;
4435 end = xmlAutomataNewState(ctxt->am);
4436
4437 /*
4438 * iterate over the subtypes and remerge the end with an
4439 * epsilon transition
4440 */
4441 if (type->maxOccurs == 1) {
4442 subtypes = type->subtypes;
4443 while (subtypes != NULL) {
4444 ctxt->state = start;
4445 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4446 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4447 subtypes = subtypes->next;
4448 }
4449 } else {
4450 int counter;
4451 xmlAutomataStatePtr hop;
4452 int maxOccurs = type->maxOccurs == UNBOUNDED ?
4453 UNBOUNDED : type->maxOccurs - 1;
4454 int minOccurs =
4455 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
4456
4457 /*
4458 * use a counter to keep track of the number of transtions
4459 * which went through the choice.
4460 */
4461 counter =
4462 xmlAutomataNewCounter(ctxt->am, minOccurs,
4463 maxOccurs);
4464 hop = xmlAutomataNewState(ctxt->am);
4465
4466 subtypes = type->subtypes;
4467 while (subtypes != NULL) {
4468 ctxt->state = start;
4469 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4470 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4471 subtypes = subtypes->next;
4472 }
4473 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4474 counter);
4475 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4476 counter);
4477 }
4478 if (type->minOccurs == 0) {
4479 xmlAutomataNewEpsilon(ctxt->am, start, end);
4480 }
4481 ctxt->state = end;
4482 break;
4483 }
4484 case XML_SCHEMA_TYPE_ALL:{
4485 xmlAutomataStatePtr start;
4486 xmlSchemaTypePtr subtypes;
4487 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4488 int lax;
4489
4490 subtypes = type->subtypes;
4491 if (subtypes == NULL)
4492 break;
4493 start = ctxt->state;
4494 while (subtypes != NULL) {
4495 ctxt->state = start;
4496 /*
4497 * the following 'if' was needed to fix bug139897
4498 * not quite sure why it only needs to be done for
4499 * elements with a 'ref', but it seems to work ok.
4500 */
4501 if (subtypes->ref != NULL)
4502 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4503 elem = (xmlSchemaElementPtr) subtypes;
4504
4505 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4506 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4507 ctxt->state, elem->name, 1,
4508 1, subtypes);
4509 } else {
4510 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4511 ctxt->state, elem->name,
4512 elem->minOccurs,
4513 elem->maxOccurs,
4514 subtypes);
4515 }
4516 subtypes = subtypes->next;
4517 }
4518 lax = type->minOccurs == 0;
4519 ctxt->state =
4520 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4521 lax);
4522 break;
4523 }
4524 case XML_SCHEMA_TYPE_RESTRICTION:
4525 if (type->subtypes != NULL)
4526 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4527 break;
4528 case XML_SCHEMA_TYPE_EXTENSION:
4529 if (type->baseType != NULL) {
4530 xmlSchemaTypePtr subtypes;
4531
4532 if (type->recurse) {
4533 xmlSchemaPErr(ctxt, type->node,
4534 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4535 "Schemas: extension type %s is recursive\n",
4536 type->name, NULL);
4537 return;
4538 }
4539 type->recurse = 1;
4540 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
4541 type->recurse = 0;
4542 subtypes = type->subtypes;
4543 while (subtypes != NULL) {
4544 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4545 subtypes = subtypes->next;
4546 }
4547 } else if (type->subtypes != NULL)
4548 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4549 break;
4550 case XML_SCHEMA_TYPE_GROUP:
4551 if (type->subtypes == NULL) {
4552 xmlSchemaTypePtr rgroup;
4553 if (type->ref != NULL) {
4554 rgroup = xmlHashLookup2(ctxt->schema->groupDecl, type->ref,
4555 type->refNs);
4556 if (rgroup == NULL) {
4557 xmlSchemaPErr(ctxt, type->node,
4558 XML_SCHEMAP_UNKNOWN_REF,
4559 "Schemas: group %s reference %s is not found",
4560 name, type->ref);
4561 return;
4562 }
4563 xmlSchemaBuildAContentModel(rgroup, ctxt, name);
4564 break;
4565 }
4566 }
4567 case XML_SCHEMA_TYPE_COMPLEX:
4568 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4569 if (type->subtypes != NULL)
4570 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4571 break;
4572 default:
4573 xmlGenericError(xmlGenericErrorContext,
4574 "Found unexpected type %d in %s content model\n",
4575 type->type, name);
4576 return;
4577 }
4578 }
4579
4580 /**
4581 * xmlSchemaBuildContentModel:
4582 * @param elem the element
4583 * @param ctxt the schema parser context
4584 * @param name the element name
4585 *
4586 * Builds the content model of the element.
4587 */
4588 static void
xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)4589 xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
4590 xmlSchemaParserCtxtPtr ctxt,
4591 const xmlChar * name)
4592 {
4593 xmlAutomataStatePtr start;
4594
4595 if (elem->contModel != NULL)
4596 return;
4597 if (elem->subtypes == NULL) {
4598 elem->contentType = XML_SCHEMA_CONTENT_ANY;
4599 return;
4600 }
4601 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
4602 return;
4603 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
4604 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
4605 return;
4606
4607 #ifdef DEBUG_CONTENT
4608 xmlGenericError(xmlGenericErrorContext,
4609 "Building content model for %s\n", name);
4610 #endif
4611
4612 ctxt->am = xmlNewAutomata();
4613 if (ctxt->am == NULL) {
4614 xmlGenericError(xmlGenericErrorContext,
4615 "Cannot create automata for elem %s\n", name);
4616 return;
4617 }
4618 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
4619 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
4620 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
4621 elem->contModel = xmlAutomataCompile(ctxt->am);
4622 if (elem->contModel == NULL) {
4623 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
4624 "failed to compile %s content model\n", name, NULL);
4625 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
4626 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
4627 "Content model of %s is not determinist:\n", name,
4628 NULL);
4629 } else {
4630 #ifdef DEBUG_CONTENT_REGEXP
4631 xmlGenericError(xmlGenericErrorContext,
4632 "Content model of %s:\n", name);
4633 xmlRegexpPrint(stderr, elem->contModel);
4634 #endif
4635 }
4636 ctxt->state = NULL;
4637 xmlFreeAutomata(ctxt->am);
4638 ctxt->am = NULL;
4639 }
4640
4641 /**
4642 * xmlSchemaRefFixupCallback:
4643 * @param elem the schema element context
4644 * @param ctxt the schema parser context
4645 *
4646 * Free the resources associated to the schema parser context
4647 */
4648 static void
xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name,const xmlChar * context ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED)4649 xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
4650 xmlSchemaParserCtxtPtr ctxt,
4651 const xmlChar * name,
4652 const xmlChar * context ATTRIBUTE_UNUSED,
4653 const xmlChar * namespace ATTRIBUTE_UNUSED)
4654 {
4655 if ((ctxt == NULL) || (elem == NULL))
4656 return;
4657 if (elem->ref != NULL) {
4658 xmlSchemaElementPtr elemDecl;
4659
4660 if (elem->subtypes != NULL) {
4661 xmlSchemaPErr(ctxt, elem->node,
4662 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
4663 "Schemas: element %s have both ref and subtype\n",
4664 name, NULL);
4665 return;
4666 }
4667 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
4668
4669 if (elemDecl == NULL) {
4670 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
4671 "Schemas: element %s ref to %s not found\n",
4672 name, elem->ref);
4673 return;
4674 }
4675 elem->refDecl = elemDecl;
4676 } else if (elem->namedType != NULL) {
4677 xmlSchemaTypePtr typeDecl;
4678
4679 if (elem->subtypes != NULL) {
4680 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
4681 "Schemas: element %s have both type and subtype\n",
4682 name, NULL);
4683 return;
4684 }
4685 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
4686 elem->namedTypeNs);
4687
4688 if (typeDecl == NULL) {
4689 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
4690 "Schemas: element %s type %s not found\n", name,
4691 elem->namedType);
4692 return;
4693 }
4694 elem->subtypes = typeDecl;
4695 }
4696 }
4697
4698 /**
4699 * xmlSchemaParseListRefFixup:
4700 * @param type the schema type definition
4701 * @param ctxt the schema parser context
4702 *
4703 * Fixup of the itemType reference of the list type.
4704 */
4705 static void
xmlSchemaParseListRefFixup(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)4706 xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
4707 {
4708 const xmlChar *itemType, *namespace;
4709 xmlSchemaTypePtr subtype;
4710
4711 /* Handle the "itemType" attribute. */
4712 itemType = xmlGetQNameProp(ctxt, type->node, "itemType", &namespace);
4713 if (itemType != NULL) {
4714 /* Do not allow more that one item type. */
4715 if (type->subtypes != NULL) {
4716 xmlSchemaPErr(ctxt, type->node,
4717 XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE,
4718 "List %s has more than one item type defined\n",
4719 type->name, NULL);
4720 }
4721 subtype = xmlSchemaGetType(ctxt->schema, itemType, namespace);
4722 if (subtype == NULL) {
4723 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_TYPE,
4724 "List %s references an unknown item type: %s\n",
4725 type->name, xmlSchemaGetProp(ctxt, type->node,
4726 "itemType"));
4727 } else
4728 type->subtypes = subtype;
4729 }
4730 }
4731
4732 /**
4733 * xmlSchemaParseUnionRefCheck:
4734 * @param typeDecl the schema type definition
4735 * @param ctxt the schema parser context
4736 *
4737 * Checks the memberTypes references of the union type.
4738 */
4739 static void
xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)4740 xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
4741 xmlSchemaParserCtxtPtr ctxt)
4742 {
4743 const xmlChar *cur, *end, *prefix, *ncName, *namespace;
4744 xmlChar *tmp;
4745 xmlSchemaTypePtr subtype;
4746 xmlNsPtr ns;
4747 int len;
4748
4749 if ((type->type != XML_SCHEMA_TYPE_UNION) || (type->ref == NULL))
4750 return;
4751
4752 cur = type->ref;
4753 do {
4754 while (IS_BLANK_CH(*cur))
4755 cur++;
4756 end = cur;
4757 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4758 end++;
4759 if (end == cur)
4760 break;
4761 tmp = xmlStrndup(cur, end - cur);
4762 ncName = xmlSplitQName3(tmp, &len);
4763 if (ncName != NULL) {
4764 prefix = xmlDictLookup(ctxt->dict, tmp, len);
4765 } else {
4766 prefix = NULL;
4767 ncName = tmp;
4768 }
4769 ns = xmlSearchNs(type->node->doc, type->node, prefix);
4770 if (ns == NULL) {
4771 if (prefix != NULL) {
4772 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_PREFIX_UNDEFINED,
4773 "Union %s: the namespace prefix of member type "
4774 "%s is undefined\n",
4775 type->name, (const xmlChar *) tmp);
4776 }
4777 namespace = NULL;
4778 } else {
4779 namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4780 }
4781 /* Lookup the referenced type */
4782 subtype = xmlSchemaGetType(ctxt->schema, ncName, namespace);
4783 if (subtype == NULL) {
4784 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
4785 "Union %s references an unknown member type %s\n",
4786 type->name, (const xmlChar *) tmp);
4787 }
4788 xmlFree(tmp);
4789 cur = end;
4790 } while (*cur != 0);
4791 }
4792
4793 /**
4794 * xmlSchemaTypeFixup:
4795 * @param typeDecl the schema type definition
4796 * @param ctxt the schema parser context
4797 *
4798 * Fixes the content model of the type.
4799 */
4800 static void
xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)4801 xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
4802 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
4803 {
4804 if (typeDecl == NULL)
4805 return;
4806 if (name == NULL)
4807 name = typeDecl->name;
4808 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
4809 switch (typeDecl->type) {
4810 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4811 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4812 if (typeDecl->subtypes != NULL)
4813 typeDecl->contentType =
4814 typeDecl->subtypes->contentType;
4815 break;
4816 }
4817 case XML_SCHEMA_TYPE_RESTRICTION:{
4818 if (typeDecl->subtypes != NULL)
4819 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4820
4821 if (typeDecl->base != NULL) {
4822 xmlSchemaTypePtr baseType;
4823
4824 baseType =
4825 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4826 typeDecl->baseNs);
4827 if (baseType == NULL) {
4828 xmlSchemaPErr(ctxt, typeDecl->node,
4829 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4830 "Schemas: type %s base type %s not found\n",
4831 name, typeDecl->base);
4832 }
4833 typeDecl->baseType = baseType;
4834 }
4835 if (typeDecl->subtypes == NULL)
4836 if (typeDecl->baseType != NULL) {
4837 /* The base type might be not "type fixed" yet,
4838 * so do it now. */
4839 if (typeDecl->baseType->contentType ==
4840 XML_SCHEMA_CONTENT_UNKNOWN)
4841 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
4842 typeDecl->contentType =
4843 typeDecl->baseType->contentType;
4844 } else
4845 /* 1.1.1 */
4846 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4847 else if ((typeDecl->subtypes->subtypes == NULL) &&
4848 ((typeDecl->subtypes->type ==
4849 XML_SCHEMA_TYPE_ALL)
4850 || (typeDecl->subtypes->type ==
4851 XML_SCHEMA_TYPE_SEQUENCE)))
4852 /* 1.1.2 */
4853 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4854 else if ((typeDecl->subtypes->type ==
4855 XML_SCHEMA_TYPE_CHOICE)
4856 && (typeDecl->subtypes->subtypes == NULL))
4857 /* 1.1.3 */
4858 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4859 else {
4860 /* 1.2 and 2.X are applied at the other layer */
4861 typeDecl->contentType =
4862 XML_SCHEMA_CONTENT_ELEMENTS;
4863 }
4864 break;
4865 }
4866 case XML_SCHEMA_TYPE_EXTENSION:{
4867 xmlSchemaContentType explicitContentType;
4868 xmlSchemaTypePtr base;
4869
4870 if (typeDecl->base != NULL) {
4871 xmlSchemaTypePtr baseType;
4872
4873 baseType =
4874 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4875 typeDecl->baseNs);
4876 if (baseType == NULL) {
4877 xmlSchemaPErr(ctxt, typeDecl->node,
4878 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4879 "Schemas: type %s base type %s not found\n",
4880 name, typeDecl->base);
4881 }
4882 typeDecl->baseType = baseType;
4883 }
4884 if (typeDecl->subtypes != NULL)
4885 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4886
4887 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4888 if (typeDecl->subtypes == NULL)
4889 /* 1.1.1 */
4890 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4891 else if ((typeDecl->subtypes->subtypes == NULL) &&
4892 ((typeDecl->subtypes->type ==
4893 XML_SCHEMA_TYPE_ALL)
4894 || (typeDecl->subtypes->type ==
4895 XML_SCHEMA_TYPE_SEQUENCE)))
4896 /* 1.1.2 */
4897 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4898 else if ((typeDecl->subtypes->type ==
4899 XML_SCHEMA_TYPE_CHOICE)
4900 && (typeDecl->subtypes->subtypes == NULL))
4901 /* 1.1.3 */
4902 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4903
4904 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4905 typeDecl->baseNs);
4906 if (base == NULL) {
4907 xmlSchemaPErr(ctxt, typeDecl->node,
4908 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4909 "Schemas: base type %s of type %s not found\n",
4910 typeDecl->base, name);
4911 return;
4912 }
4913 if (typeDecl->recurse) {
4914 xmlSchemaPErr(ctxt, typeDecl->node,
4915 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4916 "Schemas: extension type %s is recursive\n",
4917 name, NULL);
4918 return;
4919 }
4920 typeDecl->recurse = 1;
4921 xmlSchemaTypeFixup(base, ctxt, NULL);
4922 typeDecl->recurse = 0;
4923 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4924 /* 2.1 */
4925 typeDecl->contentType = base->contentType;
4926 } else if (base->contentType ==
4927 XML_SCHEMA_CONTENT_EMPTY) {
4928 /* 2.2 imbitable ! */
4929 typeDecl->contentType =
4930 XML_SCHEMA_CONTENT_ELEMENTS;
4931 } else {
4932 /* 2.3 imbitable pareil ! */
4933 typeDecl->contentType =
4934 XML_SCHEMA_CONTENT_ELEMENTS;
4935 }
4936 break;
4937 }
4938 case XML_SCHEMA_TYPE_COMPLEX:{
4939 if (typeDecl->subtypes == NULL) {
4940 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4941
4942 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4943 typeDecl->contentType =
4944 XML_SCHEMA_CONTENT_MIXED;
4945 } else {
4946 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4947 typeDecl->contentType =
4948 XML_SCHEMA_CONTENT_MIXED;
4949 else {
4950 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4951 NULL);
4952 if (typeDecl->subtypes != NULL)
4953 typeDecl->contentType =
4954 typeDecl->subtypes->contentType;
4955 }
4956 if (typeDecl->attributes == NULL)
4957 typeDecl->attributes =
4958 typeDecl->subtypes->attributes;
4959 }
4960 break;
4961 }
4962 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4963 if (typeDecl->subtypes == NULL) {
4964 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4965 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4966 typeDecl->contentType =
4967 XML_SCHEMA_CONTENT_MIXED;
4968 } else {
4969 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4970 typeDecl->contentType =
4971 XML_SCHEMA_CONTENT_MIXED;
4972 else {
4973 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4974 NULL);
4975 if (typeDecl->subtypes != NULL)
4976 typeDecl->contentType =
4977 typeDecl->subtypes->contentType;
4978 }
4979 if (typeDecl->attributes == NULL)
4980 typeDecl->attributes =
4981 typeDecl->subtypes->attributes;
4982 }
4983 break;
4984 }
4985 case XML_SCHEMA_TYPE_SEQUENCE:
4986 case XML_SCHEMA_TYPE_GROUP:
4987 case XML_SCHEMA_TYPE_ALL:
4988 case XML_SCHEMA_TYPE_CHOICE:
4989 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4990 break;
4991 case XML_SCHEMA_TYPE_BASIC:
4992 case XML_SCHEMA_TYPE_ANY:
4993 case XML_SCHEMA_TYPE_FACET:
4994 case XML_SCHEMA_TYPE_SIMPLE:
4995 case XML_SCHEMA_TYPE_UR:
4996 case XML_SCHEMA_TYPE_ELEMENT:
4997 case XML_SCHEMA_TYPE_ATTRIBUTE:
4998 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4999 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
5000 case XML_SCHEMA_TYPE_NOTATION:
5001 case XML_SCHEMA_TYPE_LIST:
5002 xmlSchemaParseListRefFixup(typeDecl, ctxt);
5003 case XML_SCHEMA_TYPE_UNION:
5004 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
5005 case XML_SCHEMA_FACET_MININCLUSIVE:
5006 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5007 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5008 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5009 case XML_SCHEMA_FACET_TOTALDIGITS:
5010 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5011 case XML_SCHEMA_FACET_PATTERN:
5012 case XML_SCHEMA_FACET_ENUMERATION:
5013 case XML_SCHEMA_FACET_WHITESPACE:
5014 case XML_SCHEMA_FACET_LENGTH:
5015 case XML_SCHEMA_FACET_MAXLENGTH:
5016 case XML_SCHEMA_FACET_MINLENGTH:
5017 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
5018 if (typeDecl->subtypes != NULL)
5019 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
5020 break;
5021 }
5022 }
5023 #ifdef DEBUG_TYPE
5024 if (typeDecl->node != NULL) {
5025 xmlGenericError(xmlGenericErrorContext,
5026 "Type of %s : %s:%d :", name,
5027 typeDecl->node->doc->URL,
5028 #ifdef LIBXML_ENABLE_NODE_LINEINFO
5029 xmlGetLineNo(typeDecl->node)
5030 #else
5031 0
5032 #endif
5033 );
5034 } else {
5035 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
5036 }
5037 switch (typeDecl->contentType) {
5038 case XML_SCHEMA_CONTENT_SIMPLE:
5039 xmlGenericError(xmlGenericErrorContext, "simple\n");
5040 break;
5041 case XML_SCHEMA_CONTENT_ELEMENTS:
5042 xmlGenericError(xmlGenericErrorContext, "elements\n");
5043 break;
5044 case XML_SCHEMA_CONTENT_UNKNOWN:
5045 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
5046 break;
5047 case XML_SCHEMA_CONTENT_EMPTY:
5048 xmlGenericError(xmlGenericErrorContext, "empty\n");
5049 break;
5050 case XML_SCHEMA_CONTENT_MIXED:
5051 xmlGenericError(xmlGenericErrorContext, "mixed\n");
5052 break;
5053 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5054 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
5055 break;
5056 case XML_SCHEMA_CONTENT_BASIC:
5057 xmlGenericError(xmlGenericErrorContext, "basic\n");
5058 break;
5059 default:
5060 xmlGenericError(xmlGenericErrorContext,
5061 "not registered !!!\n");
5062 break;
5063 }
5064 #endif
5065 }
5066
5067 ///#if defined(LIBXML_SCHEMAS_ENABLED)
5068 /**
5069 * xmlSchemaCheckFacet:
5070 * @param facet the facet
5071 * @param typeDecl the schema type definition
5072 * @param ctxt the schema parser context or NULL
5073 * @param name name of the type
5074 *
5075 * Checks the default values types, especially for facets
5076 *
5077 * Returns 0 if okay or -1 in cae of error
5078 */
5079 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)5080 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
5081 xmlSchemaTypePtr typeDecl,
5082 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
5083 {
5084 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
5085 int ret = 0;
5086
5087 if (nonNegativeIntegerType == NULL) {
5088 nonNegativeIntegerType =
5089 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
5090 xmlSchemaNs);
5091 }
5092 switch (facet->type) {
5093 case XML_SCHEMA_FACET_MININCLUSIVE:
5094 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5095 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5096 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
5097 /*
5098 * Okay we need to validate the value
5099 * at that point.
5100 */
5101 xmlSchemaValidCtxtPtr vctxt;
5102
5103 vctxt = xmlSchemaNewValidCtxt(NULL);
5104 if (vctxt == NULL)
5105 break;
5106 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
5107 facet->value);
5108 facet->val = vctxt->value;
5109 vctxt->value = NULL;
5110 if (facet->val == NULL) {
5111 /* error code */
5112 if (ctxt != NULL) {
5113 xmlSchemaPErr(ctxt, facet->node,
5114 XML_SCHEMAP_INVALID_FACET,
5115 "Schemas: type %s facet value %s invalid\n",
5116 name, facet->value);
5117 }
5118 ret = -1;
5119 }
5120 xmlSchemaFreeValidCtxt(vctxt);
5121 break;
5122 }
5123 case XML_SCHEMA_FACET_ENUMERATION:{
5124 /*
5125 * Okay we need to validate the value
5126 * at that point.
5127 */
5128 xmlSchemaValidCtxtPtr vctxt;
5129 int tmp;
5130
5131 vctxt = xmlSchemaNewValidCtxt(NULL);
5132 if (vctxt == NULL)
5133 break;
5134 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
5135 facet->value);
5136 if (tmp != 0) {
5137 if (ctxt != NULL) {
5138 xmlSchemaPErr(ctxt, facet->node,
5139 XML_SCHEMAP_INVALID_ENUM,
5140 "Schemas: type %s enumeration value %s invalid\n",
5141 name, facet->value);
5142 }
5143 ret = -1;
5144 }
5145 xmlSchemaFreeValidCtxt(vctxt);
5146 break;
5147 }
5148 case XML_SCHEMA_FACET_PATTERN:
5149 facet->regexp = xmlRegexpCompile(facet->value);
5150 if (facet->regexp == NULL) {
5151 xmlSchemaPErr(ctxt, typeDecl->node,
5152 XML_SCHEMAP_REGEXP_INVALID,
5153 "Schemas: type %s facet regexp %s invalid\n",
5154 name, facet->value);
5155 ret = -1;
5156 }
5157 break;
5158 case XML_SCHEMA_FACET_TOTALDIGITS:
5159 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5160 case XML_SCHEMA_FACET_LENGTH:
5161 case XML_SCHEMA_FACET_MAXLENGTH:
5162 case XML_SCHEMA_FACET_MINLENGTH:{
5163 int tmp;
5164
5165 tmp =
5166 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
5167 facet->value,
5168 &facet->val);
5169 if (tmp != 0) {
5170 /* error code */
5171 if (ctxt != NULL) {
5172 xmlSchemaPErr(ctxt, facet->node,
5173 XML_SCHEMAP_INVALID_FACET_VALUE,
5174 "Schemas: type %s facet value %s invalid\n",
5175 name, facet->value);
5176 }
5177 ret = -1;
5178 }
5179 break;
5180 }
5181 case XML_SCHEMA_FACET_WHITESPACE:{
5182 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
5183 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
5184 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
5185 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
5186 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
5187 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
5188 } else {
5189 if (ctxt != NULL) {
5190 xmlSchemaPErr(ctxt, facet->node,
5191 XML_SCHEMAP_INVALID_WHITE_SPACE,
5192 "Schemas: type %s whiteSpace value %s invalid\n",
5193 name, facet->value);
5194 }
5195 ret = -1;
5196 }
5197 }
5198 default:
5199 break;
5200 }
5201 return (ret);
5202 }
5203
5204 /**
5205 * xmlSchemaCheckDefaults:
5206 * @param typeDecl the schema type definition
5207 * @param ctxt the schema parser context
5208 *
5209 * Checks the default values types, especially for facets
5210 */
5211 static void
xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)5212 xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
5213 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
5214 {
5215 if (name == NULL)
5216 name = typeDecl->name;
5217 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
5218 if (typeDecl->facets != NULL) {
5219 xmlSchemaFacetPtr facet = typeDecl->facets;
5220
5221 while (facet != NULL) {
5222 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
5223 facet = facet->next;
5224 }
5225 }
5226 }
5227 }
5228
5229 /**
5230 * xmlSchemaAttrGrpFixup:
5231 * @param attrgrpDecl the schema attribute definition
5232 * @param ctxt the schema parser context
5233 * @param name the attribute name
5234 *
5235 * Fixes finish doing the computations on the attributes definitions
5236 */
5237 static void
xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)5238 xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
5239 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
5240 {
5241 if (name == NULL)
5242 name = attrgrpDecl->name;
5243 if (attrgrpDecl->attributes != NULL)
5244 return;
5245 if (attrgrpDecl->ref != NULL) {
5246 xmlSchemaAttributeGroupPtr ref;
5247
5248 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
5249 attrgrpDecl->refNs);
5250 if (ref == NULL) {
5251 xmlSchemaPErr(ctxt, attrgrpDecl->node,
5252 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
5253 "Schemas: attribute group %s reference %s not found\n",
5254 name, attrgrpDecl->ref);
5255 return;
5256 }
5257 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
5258 attrgrpDecl->attributes = ref->attributes;
5259 } else {
5260 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
5261 "Schemas: attribute %s has no attributes nor reference\n",
5262 name, NULL);
5263 }
5264 }
5265
5266 /**
5267 * xmlSchemaAttrFixup:
5268 * @param attrDecl the schema attribute definition
5269 * @param ctxt the schema parser context
5270 * @param name the attribute name
5271 *
5272 * Fixes finish doing the computations on the attributes definitions
5273 */
5274 static void
xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,xmlSchemaParserCtxtPtr ctxt,const xmlChar * name)5275 xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
5276 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
5277 {
5278 if (name == NULL)
5279 name = attrDecl->name;
5280 if (attrDecl->subtypes != NULL)
5281 return;
5282 if (attrDecl->typeName != NULL) {
5283 xmlSchemaTypePtr type;
5284
5285 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
5286 attrDecl->typeNs);
5287 if (type == NULL) {
5288 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
5289 "Schemas: attribute %s type %s not found\n",
5290 name, attrDecl->typeName);
5291 }
5292 attrDecl->subtypes = type;
5293 } else if (attrDecl->ref != NULL) {
5294 xmlSchemaAttributePtr ref;
5295
5296 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
5297 attrDecl->refNs);
5298 if (ref == NULL) {
5299 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
5300 "Schemas: attribute %s reference %s not found\n",
5301 name, attrDecl->ref);
5302 return;
5303 }
5304 xmlSchemaAttrFixup(ref, ctxt, NULL);
5305 attrDecl->subtypes = ref->subtypes;
5306 } else if (attrDecl->type != XML_SCHEMA_TYPE_ANY_ATTRIBUTE) {
5307 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
5308 "Schemas: attribute %s has no type nor reference\n",
5309 name, NULL);
5310 }
5311 }
5312
5313 /**
5314 * xmlSchemaParse:
5315 * @param ctxt a schema validation context
5316 *
5317 * parse a schema definition resource and build an internal
5318 * XML Shema struture which can be used to validate instances.
5319 * *WARNING* this interface is highly subject to change
5320 *
5321 * Returns the internal XML Schema structure built from the resource or
5322 * NULL in case of error
5323 */
5324 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)5325 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
5326 {
5327 xmlSchemaPtr ret = NULL;
5328 xmlDocPtr doc;
5329 xmlNodePtr root;
5330 int nberrors;
5331 int preserve = 0;
5332
5333 xmlSchemaInitTypes();
5334
5335 if (ctxt == NULL)
5336 return (NULL);
5337
5338 nberrors = ctxt->nberrors;
5339 ctxt->nberrors = 0;
5340 ctxt->counter = 0;
5341 ctxt->container = NULL;
5342
5343 /*
5344 * First step is to parse the input document into an DOM/Infoset
5345 */
5346 if (ctxt->URL != NULL) {
5347 doc = xmlReadFile((const char *) ctxt->URL, NULL,
5348 SCHEMAS_PARSE_OPTIONS);
5349 if (doc == NULL) {
5350 xmlSchemaPErr(ctxt, NULL,
5351 XML_SCHEMAP_FAILED_LOAD,
5352 "xmlSchemaParse: could not load %s\n",
5353 ctxt->URL, NULL);
5354 return (NULL);
5355 }
5356 } else if (ctxt->buffer != NULL) {
5357 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
5358 SCHEMAS_PARSE_OPTIONS);
5359 if (doc == NULL) {
5360 xmlSchemaPErr(ctxt, NULL,
5361 XML_SCHEMAP_FAILED_PARSE,
5362 "xmlSchemaParse: could not parse\n",
5363 NULL, NULL);
5364 return (NULL);
5365 }
5366 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
5367 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
5368 } else if (ctxt->doc != NULL) {
5369 doc = ctxt->doc;
5370 preserve = 1;
5371 } else {
5372 xmlSchemaPErr(ctxt, NULL,
5373 XML_SCHEMAP_NOTHING_TO_PARSE,
5374 "xmlSchemaParse: could not parse\n",
5375 NULL, NULL);
5376 return (NULL);
5377 }
5378
5379 /*
5380 * Then extract the root and Schema parse it
5381 */
5382 root = xmlDocGetRootElement(doc);
5383 if (root == NULL) {
5384 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
5385 XML_SCHEMAP_NOROOT,
5386 "schemas has no root", NULL, NULL);
5387 if (!preserve) {
5388 xmlFreeDoc(doc);
5389 }
5390 return (NULL);
5391 }
5392
5393 /*
5394 * Remove all the blank text nodes
5395 */
5396 xmlSchemaCleanupDoc(ctxt, root);
5397
5398 /*
5399 * Then do the parsing for good
5400 */
5401 ret = xmlSchemaParseSchema(ctxt, root);
5402 if (ret == NULL) {
5403 if (!preserve) {
5404 xmlFreeDoc(doc);
5405 }
5406 return (NULL);
5407 }
5408 ret->doc = doc;
5409 ret->preserve = preserve;
5410
5411 /*
5412 * Then fix all the references.
5413 */
5414 ctxt->schema = ret;
5415 xmlHashScanFull(ret->elemDecl,
5416 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
5417
5418 /*
5419 * Then fixup all attributes declarations
5420 */
5421 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
5422
5423 /*
5424 * Then fixup all attributes group declarations
5425 */
5426 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
5427 ctxt);
5428
5429 /*
5430 * Then fixup all types properties
5431 */
5432 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
5433
5434 /*
5435 * Then build the content model for all elements
5436 */
5437 xmlHashScan(ret->elemDecl,
5438 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
5439
5440 /*
5441 * Then check the defaults part of the type like facets values
5442 */
5443 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
5444 ctxt);
5445
5446 if (ctxt->nberrors != 0) {
5447 xmlSchemaFree(ret);
5448 ret = NULL;
5449 }
5450 return (ret);
5451 }
5452
5453 /**
5454 * xmlSchemaSetParserErrors:
5455 * @param ctxt a schema validation context
5456 * @param err the error callback
5457 * @param warn the warning callback
5458 * @param ctx contextual data for the callbacks
5459 *
5460 * Set the callback functions used to handle errors for a validation context
5461 */
5462 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)5463 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
5464 xmlSchemaValidityErrorFunc err,
5465 xmlSchemaValidityWarningFunc warn, void *ctx)
5466 {
5467 if (ctxt == NULL)
5468 return;
5469 ctxt->error = err;
5470 ctxt->warning = warn;
5471 ctxt->userData = ctx;
5472 }
5473
5474 /**
5475 * xmlSchemaFacetTypeToString:
5476 * @param type the facet type
5477 *
5478 * Convert the xmlSchemaTypeType to a char string.
5479 *
5480 * Returns the char string representation of the facet type if the
5481 * type is a facet and an "Internal Error" string otherwise.
5482 */
5483 static const char *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)5484 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5485 {
5486 switch (type) {
5487 case XML_SCHEMA_FACET_PATTERN:
5488 return ("pattern");
5489 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5490 return ("maxExclusive");
5491 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5492 return ("maxInclusive");
5493 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5494 return ("minExclusive");
5495 case XML_SCHEMA_FACET_MININCLUSIVE:
5496 return ("minInclusive");
5497 case XML_SCHEMA_FACET_WHITESPACE:
5498 return ("whiteSpace");
5499 case XML_SCHEMA_FACET_ENUMERATION:
5500 return ("enumeration");
5501 case XML_SCHEMA_FACET_LENGTH:
5502 return ("length");
5503 case XML_SCHEMA_FACET_MAXLENGTH:
5504 return ("maxLength");
5505 case XML_SCHEMA_FACET_MINLENGTH:
5506 return ("minLength");
5507 case XML_SCHEMA_FACET_TOTALDIGITS:
5508 return ("totalDigits");
5509 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5510 return ("fractionDigits");
5511 default:
5512 break;
5513 }
5514 return ("Internal Error");
5515 }
5516
5517 /**
5518 * xmlSchemaValidateFacetsInternal:
5519 * @param ctxt a schema validation context
5520 * @param base the base type
5521 * @param facets the list of facets to check
5522 * @param value the lexical repr of the value to validate
5523 * @param val the precomputed value
5524 * @param fireErrors if 0, only internal errors will be fired;
5525 * otherwise all errors will be fired.
5526 *
5527 * Check a value against all facet conditions
5528 *
5529 * Returns 0 if the element is schemas valid, a positive error code
5530 * number otherwise and -1 in case of internal or API error.
5531 */
5532 static int
xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,xmlSchemaTypePtr base,xmlSchemaFacetPtr facets,const xmlChar * value,int fireErrors)5533 xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
5534 xmlSchemaTypePtr base,
5535 xmlSchemaFacetPtr facets,
5536 const xmlChar * value, int fireErrors)
5537 {
5538 int ret = 0;
5539 int tmp = 0;
5540 xmlSchemaTypeType type;
5541 xmlSchemaFacetPtr facet = facets;
5542
5543 while (facet != NULL) {
5544 type = facet->type;
5545 if (type == XML_SCHEMA_FACET_ENUMERATION) {
5546 tmp = 1;
5547
5548 while (facet != NULL) {
5549 tmp =
5550 xmlSchemaValidateFacet(base, facet, value,
5551 ctxt->value);
5552 if (tmp == 0) {
5553 return 0;
5554 }
5555 facet = facet->next;
5556 }
5557 } else
5558 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
5559
5560 if (tmp != 0) {
5561 ret = tmp;
5562 if (fireErrors)
5563 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET,
5564 "Failed to validate type with facet %s\n",
5565 (const xmlChar *) xmlSchemaFacetTypeToString(type),
5566 NULL);
5567 }
5568 if (facet != NULL)
5569 facet = facet->next;
5570 }
5571 return (ret);
5572 }
5573
5574 /**
5575 * xmlSchemaValidateFacets:
5576 * @param ctxt a schema validation context
5577 * @param base the base type
5578 * @param facets the list of facets to check
5579 * @param value the lexical repr of the value to validate
5580 * @param val the precomputed value
5581 *
5582 * Check a value against all facet conditions
5583 *
5584 * Returns 0 if the element is schemas valid, a positive error code
5585 * number otherwise and -1 in case of internal or API error.
5586 */
5587 static int
xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,xmlSchemaTypePtr base,xmlSchemaFacetPtr facets,const xmlChar * value)5588 xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5589 xmlSchemaTypePtr base,
5590 xmlSchemaFacetPtr facets, const xmlChar * value)
5591 {
5592 return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
5593 }
5594
5595 /************************************************************************
5596 * *
5597 * Simple type validation *
5598 * *
5599 ************************************************************************/
5600
5601 /**
5602 * xmlSchemaValidateSimpleValueUnion:
5603 * @param ctxt a schema validation context
5604 * @param type the type declaration
5605 * @param value the value to validate
5606 *
5607 * Validates a value against a union.
5608 *
5609 * Returns 0 if the value is valid, a positive error code
5610 * number otherwise and -1 in case of internal or API error.
5611 */
5612 static int
xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,xmlSchemaTypePtr type,const xmlChar * value)5613 xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
5614 xmlSchemaTypePtr type, const xmlChar * value)
5615 {
5616 int ret = 0;
5617 const xmlChar *cur, *end, *prefix, *ncName;
5618 xmlChar *tmp;
5619 xmlSchemaTypePtr subtype;
5620 xmlNsPtr ns;
5621 int len;
5622
5623
5624 /* Process referenced memberTypes. */
5625 cur = type->ref;
5626 do {
5627 while (IS_BLANK_CH(*cur))
5628 cur++;
5629 end = cur;
5630 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5631 end++;
5632 if (end == cur)
5633 break;
5634 tmp = xmlStrndup(cur, end - cur);
5635 ncName = xmlSplitQName3(tmp, &len);
5636 if (ncName != NULL) {
5637 prefix = xmlStrndup(tmp, len);
5638 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
5639 } else {
5640 prefix = NULL;
5641 ncName = tmp;
5642 }
5643 /* We won't do additional checks here,
5644 * since they have been performed during parsing. */
5645 ns = xmlSearchNs(type->node->doc, type->node, prefix);
5646 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
5647 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
5648 if (tmp != NULL)
5649 xmlFree(tmp);
5650 if (prefix != NULL)
5651 xmlFree((void *)prefix);
5652 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5653 if ((ret == 0) || (ret == -1)) {
5654 return (ret);
5655 }
5656 cur = end;
5657 } while (*cur != 0);
5658
5659 if (type->subtypes != NULL) {
5660 subtype = type->subtypes;
5661 do {
5662 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5663 if ((ret == 0) || (ret == -1)) {
5664 return (ret);
5665 }
5666 subtype = subtype->next;
5667 } while (subtype != NULL);
5668 }
5669 return (ret);
5670 }
5671
5672 /**
5673 * xmlSchemaValidateSimpleValue:
5674 * @param ctxt a schema validation context
5675 * @param type the type declaration
5676 * @param value the value to validate
5677 *
5678 * Validate a value against a simple type
5679 *
5680 * Returns 0 if the value is valid, a positive error code
5681 * number otherwise and -1 in case of internal or API error.
5682 */
5683 static int
xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,xmlSchemaTypePtr type,const xmlChar * value)5684 xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
5685 xmlSchemaTypePtr type, const xmlChar * value)
5686 {
5687 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
5688 }
5689
5690 /**
5691 * xmlSchemaValidateSimpleValue:
5692 * @param ctxt a schema validation context
5693 * @param type the type declaration
5694 * @param value the value to validate
5695 * @param fireErrors if 0, only internal errors will be fired;
5696 * otherwise all errors will be fired.
5697 *
5698 * Validate a value against a simple type
5699 *
5700 * Returns 0 if the value is valid, a positive error code
5701 * number otherwise and -1 in case of internal or API error.
5702 */
5703 static int
xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,xmlSchemaTypePtr type,const xmlChar * value,int fireErrors)5704 xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
5705 xmlSchemaTypePtr type,
5706 const xmlChar * value,
5707 int fireErrors)
5708 {
5709 int ret = 0;
5710
5711 /*
5712 * First normalize the value accordingly to Schema Datatype
5713 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
5714 *
5715 * Then check the normalized value against the lexical space of the
5716 * type.
5717 */
5718 if (type->type == XML_SCHEMA_TYPE_BASIC) {
5719 if (ctxt->value != NULL) {
5720 xmlSchemaFreeValue(ctxt->value);
5721 ctxt->value = NULL;
5722 }
5723 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5724 ctxt->cur);
5725 if ((fireErrors) && (ret != 0)) {
5726 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
5727 "Failed to validate basic type %s\n",
5728 type->name, NULL);
5729 }
5730 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
5731 xmlSchemaTypePtr base;
5732 xmlSchemaFacetPtr facet;
5733
5734 base = type->baseType;
5735 if (base != NULL) {
5736 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5737 value, fireErrors);
5738 } else if (type->subtypes != NULL) {
5739 TODO
5740 }
5741
5742 /*
5743 * Do not validate facets or attributes when working on
5744 * building the Schemas
5745 */
5746 if (ctxt->schema != NULL) {
5747 if (ret == 0) {
5748 facet = type->facets;
5749 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet,
5750 value, fireErrors);
5751 }
5752 }
5753 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
5754 xmlSchemaTypePtr base;
5755
5756 base = type->subtypes;
5757 if (base != NULL) {
5758 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5759 value, fireErrors);
5760 } else {
5761 TODO}
5762 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
5763 xmlSchemaTypePtr base;
5764 const xmlChar *cur, *end;
5765 xmlChar *tmp;
5766 int ret2;
5767
5768 base = type->subtypes;
5769 if (base == NULL) {
5770 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5771 "Internal: List type %s has no base type\n",
5772 type->name, NULL);
5773 return (-1);
5774 }
5775 cur = value;
5776 do {
5777 while (IS_BLANK_CH(*cur))
5778 cur++;
5779 end = cur;
5780 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5781 end++;
5782 if (end == cur)
5783 break;
5784 tmp = xmlStrndup(cur, end - cur);
5785 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5786 tmp, fireErrors);
5787 xmlFree(tmp);
5788 if (ret2 != 0)
5789 ret = 1;
5790 cur = end;
5791 } while (*cur != 0);
5792 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
5793 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
5794 if ((fireErrors) && (ret != 0)) {
5795 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
5796 "Failed to validate type %s\n", type->name, NULL);
5797 }
5798 } else {
5799 TODO
5800 }
5801 return (ret);
5802 }
5803
5804 /************************************************************************
5805 * *
5806 * DOM Validation code *
5807 * *
5808 ************************************************************************/
5809
5810 static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
5811 xmlNodePtr node);
5812 static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
5813 xmlNodePtr elem,
5814 xmlSchemaAttributePtr attributes);
5815 static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
5816 xmlNodePtr elem,
5817 xmlSchemaElementPtr elemDecl,
5818 xmlSchemaTypePtr type);
5819
5820 /**
5821 * xmlSchemaRegisterAttributes:
5822 * @param ctxt a schema validation context
5823 * @param attrs a list of attributes
5824 *
5825 * Register the list of attributes as the set to be validated on that element
5826 *
5827 * Returns -1 in case of error, 0 otherwise
5828 */
5829 static int
xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt,xmlAttrPtr attrs)5830 xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5831 {
5832 while (attrs != NULL) {
5833 if ((attrs->ns != NULL) &&
5834 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5835 attrs = attrs->next;
5836 continue;
5837 }
5838 if (ctxt->attrNr >= ctxt->attrMax) {
5839 xmlSchemaAttrStatePtr tmp;
5840
5841 ctxt->attrMax *= 2;
5842 tmp = (xmlSchemaAttrStatePtr)
5843 xmlRealloc(ctxt->attr, ctxt->attrMax *
5844 sizeof(xmlSchemaAttrState));
5845 if (tmp == NULL) {
5846 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5847 ctxt->attrMax /= 2;
5848 return (-1);
5849 }
5850 ctxt->attr = tmp;
5851 }
5852 ctxt->attr[ctxt->attrNr].attr = attrs;
5853 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5854 ctxt->attrNr++;
5855 attrs = attrs->next;
5856 }
5857 return (0);
5858 }
5859
5860 /**
5861 * xmlSchemaCheckAttributes:
5862 * @param ctxt a schema validation context
5863 * @param node the node carrying it.
5864 *
5865 * Check that the registered set of attributes on the current node
5866 * has been properly validated.
5867 *
5868 * Returns 0 if validity constraints are met, 1 otherwise.
5869 */
5870 static int
xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node)5871 xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5872 {
5873 int ret = 0;
5874 int i;
5875
5876 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5877 if (ctxt->attr[i].attr == NULL)
5878 break;
5879 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5880 ret = 1;
5881 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
5882 "Attribute %s on %s is unknown\n",
5883 ctxt->attr[i].attr->name, node->name);
5884 }
5885 }
5886 return (ret);
5887 }
5888
5889 #if 0 /* Not currently used - remove if ever needed */
5890 /**
5891 * xmlSchemaValidateSimpleContent:
5892 * @param ctxt a schema validation context
5893 * @param elem an element
5894 * @param type the type declaration
5895 *
5896 * Validate the content of an element expected to be a simple type
5897 *
5898 * Returns 0 if the element is schemas valid, a positive error code
5899 * number otherwise and -1 in case of internal or API error.
5900 */
5901 static int
5902 xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
5903 xmlNodePtr node ATTRIBUTE_UNUSED)
5904 {
5905 xmlNodePtr child;
5906 xmlSchemaTypePtr type, base;
5907 xmlChar *value;
5908 int ret = 0;
5909
5910 child = ctxt->node;
5911 type = ctxt->type;
5912
5913 /*
5914 * Validation Rule: Element Locally Valid (Type): 3.1.3
5915 */
5916 value = xmlNodeGetContent(child);
5917 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5918 switch (type->type) {
5919 case XML_SCHEMA_TYPE_RESTRICTION:{
5920 xmlSchemaFacetPtr facet;
5921
5922 base = type->baseType;
5923 if (base != NULL) {
5924 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5925 } else {
5926 TODO}
5927 if (ret == 0) {
5928 facet = type->facets;
5929 ret =
5930 xmlSchemaValidateFacets(ctxt, base, facet, value);
5931 }
5932 if ((ret == 0) && (type->attributes != NULL)) {
5933 ret = xmlSchemaValidateAttributes(ctxt, node,
5934 type->attributes);
5935 }
5936 break;
5937 }
5938 case XML_SCHEMA_TYPE_EXTENSION:{
5939 TODO
5940 break;
5941 }
5942 default:
5943 TODO
5944 }
5945 if (value != NULL)
5946 xmlFree(value);
5947
5948 return (ret);
5949 }
5950 #endif
5951
5952 /**
5953 * xmlSchemaValidateCheckNodeList
5954 * @param nodelist the list of nodes
5955 *
5956 * Check the node list is only made of text nodes and entities pointing
5957 * to text nodes
5958 *
5959 * Returns 1 if true, 0 if false and -1 in case of error
5960 */
5961 static int
xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)5962 xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5963 {
5964 while (nodelist != NULL) {
5965 if (nodelist->type == XML_ENTITY_REF_NODE) {
5966 TODO /* implement recursion in the entity content */
5967 }
5968 if ((nodelist->type != XML_TEXT_NODE) &&
5969 (nodelist->type != XML_COMMENT_NODE) &&
5970 (nodelist->type != XML_PI_NODE) &&
5971 (nodelist->type != XML_CDATA_SECTION_NODE)) {
5972 return (0);
5973 }
5974 nodelist = nodelist->next;
5975 }
5976 return (1);
5977 }
5978
5979 /**
5980 * xmlSchemaSkipIgnored:
5981 * @param ctxt a schema validation context
5982 * @param type the current type context
5983 * @param node the top node.
5984 *
5985 * Skip ignorable nodes in that context
5986 *
5987 * Returns the new sibling
5988 * number otherwise and -1 in case of internal or API error.
5989 */
5990 static xmlNodePtr
xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaTypePtr type,xmlNodePtr node)5991 xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
5992 xmlSchemaTypePtr type, xmlNodePtr node)
5993 {
5994 int mixed = 0;
5995
5996 /*
5997 *
5998 */
5999 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
6000 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
6001 while ((node != NULL) &&
6002 ((node->type == XML_COMMENT_NODE) ||
6003 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
6004 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
6005 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
6006 node = node->next;
6007 }
6008 return (node);
6009 }
6010
6011 /**
6012 * xmlSchemaValidateCallback:
6013 * @param ctxt a schema validation context
6014 * @param name the name of the element detected (might be NULL)
6015 * @param type the type
6016 *
6017 * A transition has been made in the automata associated to an element
6018 * content model
6019 */
6020 static void
xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,const xmlChar * name ATTRIBUTE_UNUSED,xmlSchemaTypePtr type,xmlNodePtr node)6021 xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
6022 const xmlChar * name ATTRIBUTE_UNUSED,
6023 xmlSchemaTypePtr type, xmlNodePtr node)
6024 {
6025 xmlSchemaTypePtr oldtype = ctxt->type;
6026 xmlNodePtr oldnode = ctxt->node;
6027
6028 #ifdef DEBUG_CONTENT
6029 xmlGenericError(xmlGenericErrorContext,
6030 "xmlSchemaValidateCallback: %s, %s, %s\n",
6031 name, type->name, node->name);
6032 #endif
6033 ctxt->type = type;
6034 ctxt->node = node;
6035 xmlSchemaValidateContent(ctxt, node);
6036 ctxt->type = oldtype;
6037 ctxt->node = oldnode;
6038 }
6039
6040
6041 #if 0
6042
6043 /**
6044 * xmlSchemaValidateSimpleRestrictionType:
6045 * @param ctxt a schema validation context
6046 * @param node the top node.
6047 *
6048 * Validate the content of a restriction type.
6049 *
6050 * Returns 0 if the element is schemas valid, a positive error code
6051 * number otherwise and -1 in case of internal or API error.
6052 */
6053 static int
6054 xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
6055 xmlNodePtr node)
6056 {
6057 xmlNodePtr child;
6058 xmlSchemaTypePtr type;
6059 int ret;
6060
6061 child = ctxt->node;
6062 type = ctxt->type;
6063
6064 if ((ctxt == NULL) || (type == NULL)) {
6065 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6066 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
6067 node->name, NULL);
6068 return (-1);
6069 }
6070 /*
6071 * Only text and text based entities references shall be found there
6072 */
6073 ret = xmlSchemaValidateCheckNodeList(child);
6074 if (ret < 0) {
6075 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6076 "Internal error: xmlSchemaValidateSimpleType %s content\n",
6077 node->name, NULL);
6078 return (-1);
6079 } else if (ret == 0) {
6080 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
6081 "Element %s content is not a simple type\n",
6082 node->name, NULL);
6083 return (-1);
6084 }
6085 ctxt->type = type->subtypes;
6086 xmlSchemaValidateContent(ctxt, node);
6087 ctxt->type = type;
6088 return (ret);
6089 }
6090 #endif
6091
6092 /**
6093 * xmlSchemaValidateSimpleType:
6094 * @param ctxt a schema validation context
6095 * @param node the top node.
6096 *
6097 * Validate the content of an simple type.
6098 *
6099 * Returns 0 if the element is schemas valid, a positive error code
6100 * number otherwise and -1 in case of internal or API error.
6101 */
6102 static int
xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node)6103 xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6104 {
6105 xmlNodePtr child;
6106 xmlSchemaTypePtr type, base, variety;
6107 xmlAttrPtr attr;
6108 int ret;
6109 xmlChar *value;
6110
6111
6112 child = ctxt->node;
6113 type = ctxt->type;
6114
6115 if ((ctxt == NULL) || (type == NULL)) {
6116 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6117 "Internal error: xmlSchemaValidateSimpleType %s\n",
6118 node->name, NULL);
6119 return (-1);
6120 }
6121 /*
6122 * Only text and text based entities references shall be found there
6123 */
6124 ret = xmlSchemaValidateCheckNodeList(child);
6125 if (ret < 0) {
6126 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6127 "Internal error: xmlSchemaValidateSimpleType %s content\n",
6128 node->name, NULL);
6129 return (-1);
6130 } else if (ret == 0) {
6131 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
6132 "Element %s content is not a simple type\n",
6133 node->name, NULL);
6134 return (-1);
6135 }
6136 /*
6137 * Validation Rule: Element Locally Valid (Type): 3.1.1
6138 */
6139
6140 attr = node->properties;
6141 while (attr != NULL) {
6142 if ((attr->ns == NULL) ||
6143 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
6144 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6145 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
6146 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
6147 (!xmlStrEqual
6148 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
6149 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
6150 "Element %s: attribute %s should not be present\n",
6151 node->name, attr->name);
6152 return (ctxt->err);
6153 }
6154 }
6155 /*
6156 * If {variety} is �atomic� then the {variety} of {base type definition}
6157 * must be �atomic�.
6158 * If {variety} is �list� then the {variety} of {item type definition}
6159 * must be either �atomic� or �union�.
6160 * If {variety} is �union� then {member type definitions} must be a list
6161 * of datatype definitions.
6162 */
6163 if (type->subtypes == NULL) {
6164 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6165 "Internal error: xmlSchemaValidateSimpleType; "
6166 "simple type %s does not define a variety\n",
6167 node->name, NULL);
6168 return (ctxt->err);
6169 }
6170 /* Varieties: Restriction or List or Union. */
6171 variety = type->subtypes;
6172 ctxt->type = variety;
6173 value = xmlNodeGetContent(child);
6174 switch (variety->type) {
6175 case XML_SCHEMA_TYPE_RESTRICTION:{
6176 xmlSchemaFacetPtr facet;
6177
6178 base = variety->baseType;
6179 if (base != NULL) {
6180 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
6181 } else {
6182 TODO}
6183 if (ret == 0) {
6184 facet = variety->facets;
6185 ret =
6186 xmlSchemaValidateFacets(ctxt, base, facet, value);
6187 }
6188 if ((ret == 0) && (variety->attributes != NULL)) {
6189 ret = xmlSchemaValidateAttributes(ctxt, node,
6190 variety->attributes);
6191 }
6192 break;
6193 }
6194 case XML_SCHEMA_TYPE_LIST:
6195 case XML_SCHEMA_TYPE_UNION: {
6196 ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
6197 break;
6198 }
6199 default:{
6200 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6201 "Internal error: xmlSchemaValidateSimpleType; "
6202 "simple type %s defines unknown content: %s\n",
6203 variety->name, NULL);
6204 ret = ctxt->err;
6205 }
6206 }
6207 if (value != NULL)
6208 xmlFree(value);
6209
6210 /* This was removed, since a simple content is not a content of a
6211 * simple type, but of a complex type.
6212 * ret = xmlSchemaValidateSimpleContent(ctxt, node);
6213 */
6214 ctxt->type = type;
6215 return (ret);
6216 }
6217
6218 /**
6219 * xmlSchemaValidateElementType:
6220 * @param ctxt a schema validation context
6221 * @param node the top node.
6222 *
6223 * Validate the content of an element type.
6224 * Validation Rule: Element Locally Valid (Complex Type)
6225 *
6226 * Returns 0 if the element is schemas valid, a positive error code
6227 * number otherwise and -1 in case of internal or API error.
6228 */
6229 static int
xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node)6230 xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6231 {
6232 xmlNodePtr child;
6233 xmlSchemaTypePtr type;
6234 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
6235 xmlSchemaElementPtr decl;
6236 int ret, attrBase;
6237
6238 oldregexp = ctxt->regexp;
6239
6240 child = ctxt->node;
6241 type = ctxt->type;
6242
6243 if ((ctxt == NULL) || (type == NULL)) {
6244 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6245 "Internal error: xmlSchemaValidateElementType\n",
6246 node->name, NULL);
6247 return (-1);
6248 }
6249 if (child == NULL) {
6250 if (type->minOccurs > 0) {
6251 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
6252 "Element %s: missing child %s\n",
6253 node->name, type->name);
6254 }
6255 return (ctxt->err);
6256 }
6257
6258 /*
6259 * Verify the element matches
6260 */
6261 if (!xmlStrEqual(child->name, type->name)) {
6262 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
6263 "Element %s: missing child %s found %s\n",
6264 node->name, type->name, child->name);
6265 return (ctxt->err);
6266 }
6267 /*
6268 * Verify the attributes
6269 */
6270 attrBase = ctxt->attrBase;
6271 ctxt->attrBase = ctxt->attrNr;
6272 xmlSchemaRegisterAttributes(ctxt, child->properties);
6273 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
6274 /*
6275 * Verify the element content recursively
6276 */
6277 decl = (xmlSchemaElementPtr) type;
6278 oldregexp = ctxt->regexp;
6279 if (decl->contModel != NULL) {
6280 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
6281 (xmlRegExecCallbacks)
6282 xmlSchemaValidateCallback, ctxt);
6283 #ifdef DEBUG_AUTOMATA
6284 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
6285 #endif
6286 }
6287 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
6288 type->subtypes);
6289
6290 if (decl->contModel != NULL) {
6291 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
6292 #ifdef DEBUG_AUTOMATA
6293 xmlGenericError(xmlGenericErrorContext,
6294 "====> %s : %d\n", node->name, ret);
6295 #endif
6296 if (ret == 0) {
6297 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
6298 "Element %s content check failed\n",
6299 node->name, NULL);
6300 } else if (ret < 0) {
6301 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
6302 "Element %s content check failure\n",
6303 node->name, NULL);
6304 #ifdef DEBUG_CONTENT
6305 } else {
6306 xmlGenericError(xmlGenericErrorContext,
6307 "Element %s content check succeeded\n",
6308 node->name);
6309
6310 #endif
6311 }
6312 xmlRegFreeExecCtxt(ctxt->regexp);
6313 }
6314 /*
6315 * Verify that all attributes were Schemas-validated
6316 */
6317 xmlSchemaCheckAttributes(ctxt, node);
6318 ctxt->attrNr = ctxt->attrBase;
6319 ctxt->attrBase = attrBase;
6320
6321 ctxt->regexp = oldregexp;
6322
6323 ctxt->node = child;
6324 ctxt->type = type;
6325 return (ctxt->err);
6326 }
6327
6328 /**
6329 * xmlSchemaValidateBasicType:
6330 * @param ctxt a schema validation context
6331 * @param node the top node.
6332 *
6333 * Validate the content of an element expected to be a basic type type
6334 *
6335 * Returns 0 if the element is schemas valid, a positive error code
6336 * number otherwise and -1 in case of internal or API error.
6337 */
6338 static int
xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node)6339 xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6340 {
6341 int ret;
6342 xmlNodePtr child, cur;
6343 xmlSchemaTypePtr type;
6344 xmlChar *value; /* lexical representation */
6345
6346 child = ctxt->node;
6347 type = ctxt->type;
6348
6349 if ((ctxt == NULL) || (type == NULL)) {
6350 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6351 "Internal error: xmlSchemaValidateBasicType\n",
6352 node->name, NULL);
6353 return (-1);
6354 }
6355 /*
6356 * First check the content model of the node.
6357 */
6358 cur = child;
6359 while (cur != NULL) {
6360 switch (cur->type) {
6361 case XML_TEXT_NODE:
6362 case XML_CDATA_SECTION_NODE:
6363 case XML_PI_NODE:
6364 case XML_COMMENT_NODE:
6365 case XML_XINCLUDE_START:
6366 case XML_XINCLUDE_END:
6367 break;
6368 case XML_ENTITY_REF_NODE:
6369 case XML_ENTITY_NODE:
6370 TODO break;
6371 case XML_ELEMENT_NODE:
6372 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
6373 "Element %s: child %s should not be present\n",
6374 node->name, cur->name);
6375 return (ctxt->err);
6376 case XML_ATTRIBUTE_NODE:
6377 case XML_DOCUMENT_NODE:
6378 case XML_DOCUMENT_TYPE_NODE:
6379 case XML_DOCUMENT_FRAG_NODE:
6380 case XML_NOTATION_NODE:
6381 case XML_HTML_DOCUMENT_NODE:
6382 case XML_DTD_NODE:
6383 case XML_ELEMENT_DECL:
6384 case XML_ATTRIBUTE_DECL:
6385 case XML_ENTITY_DECL:
6386 case XML_NAMESPACE_DECL:
6387 #ifdef LIBXML_DOCB_ENABLED
6388 case XML_DOCB_DOCUMENT_NODE:
6389 #endif
6390 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
6391 "Element %s: node type of node unexpected here\n",
6392 node->name, NULL);
6393 return (ctxt->err);
6394 }
6395 cur = cur->next;
6396 }
6397 if (child == NULL)
6398 value = NULL;
6399 else
6400 value = xmlNodeGetContent(child->parent);
6401
6402 if (ctxt->value != NULL) {
6403 xmlSchemaFreeValue(ctxt->value);
6404 ctxt->value = NULL;
6405 }
6406 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
6407 if (value != NULL)
6408 xmlFree(value);
6409 if (ret != 0) {
6410 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
6411 "Element %s: failed to validate basic type %s\n",
6412 node->name, type->name);
6413 }
6414 return (ret);
6415 }
6416
6417 /**
6418 * xmlSchemaValidateComplexType:
6419 * @param ctxt a schema validation context
6420 * @param node the top node.
6421 *
6422 * Validate the content of an element expected to be a complex type type
6423 * xmlschema-1.html#cvc-complex-type
6424 * Validation Rule: Element Locally Valid (Complex Type)
6425 *
6426 * Returns 0 if the element is schemas valid, a positive error code
6427 * number otherwise and -1 in case of internal or API error.
6428 */
6429 static int
xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node)6430 xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6431 {
6432 xmlNodePtr child;
6433 xmlSchemaTypePtr type, subtype;
6434 int ret;
6435
6436 child = ctxt->node;
6437 type = ctxt->type;
6438 ctxt->cur = node;
6439
6440 switch (type->contentType) {
6441 case XML_SCHEMA_CONTENT_EMPTY:
6442 if (type->baseType != NULL) {
6443 } else if (child != NULL) {
6444 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY,
6445 "Element %s is supposed to be empty\n",
6446 node->name, NULL);
6447 }
6448 if (type->attributes != NULL) {
6449 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6450 }
6451 subtype = type->subtypes;
6452 while (subtype != NULL) {
6453 ctxt->type = subtype;
6454 xmlSchemaValidateComplexType(ctxt, node);
6455 subtype = subtype->next;
6456 }
6457 break;
6458 case XML_SCHEMA_CONTENT_ELEMENTS:
6459 case XML_SCHEMA_CONTENT_MIXED:
6460 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
6461 /*
6462 * Skip ignorable nodes in that context
6463 */
6464 child = xmlSchemaSkipIgnored(ctxt, type, child);
6465 while (child != NULL) {
6466 if (child->type == XML_ELEMENT_NODE) {
6467 ret = xmlRegExecPushString(ctxt->regexp,
6468 child->name, child);
6469 #ifdef DEBUG_AUTOMATA
6470 if (ret < 0)
6471 xmlGenericError(xmlGenericErrorContext,
6472 " --> %s Error\n", child->name);
6473 else
6474 xmlGenericError(xmlGenericErrorContext,
6475 " --> %s\n", child->name);
6476 #endif
6477 }
6478 child = child->next;
6479 /*
6480 * Skip ignorable nodes in that context
6481 */
6482 child = xmlSchemaSkipIgnored(ctxt, type, child);
6483 }
6484 if (((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
6485 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS)) &&
6486 (type->subtypes != NULL)) {
6487 TODO
6488 }
6489
6490
6491 if (type->attributes != NULL) {
6492 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6493 }
6494 break;
6495 case XML_SCHEMA_CONTENT_BASIC:{
6496 if (type->subtypes != NULL) {
6497 ctxt->type = type->subtypes;
6498 xmlSchemaValidateComplexType(ctxt, node);
6499 }
6500 if (type->baseType != NULL) {
6501 ctxt->type = type->baseType;
6502 if (type->baseType->type == XML_SCHEMA_TYPE_BASIC)
6503 xmlSchemaValidateBasicType(ctxt, node);
6504 else if (type->baseType->type == XML_SCHEMA_TYPE_COMPLEX)
6505 xmlSchemaValidateComplexType(ctxt, node);
6506 else if (type->baseType->type == XML_SCHEMA_TYPE_SIMPLE)
6507 xmlSchemaValidateSimpleType(ctxt, node);
6508 else
6509 xmlGenericError(xmlGenericErrorContext,
6510 "unexpected content type of base: %d\n",
6511 type->contentType);
6512
6513 }
6514 if (type->attributes != NULL) {
6515 xmlSchemaValidateAttributes(ctxt, node,
6516 type->attributes);
6517 }
6518 ctxt->type = type;
6519 break;
6520 }
6521 case XML_SCHEMA_CONTENT_SIMPLE:{
6522 if (type->subtypes != NULL) {
6523 ctxt->type = type->subtypes;
6524 xmlSchemaValidateComplexType(ctxt, node);
6525 }
6526 if (type->baseType != NULL) {
6527 ctxt->type = type->baseType;
6528 xmlSchemaValidateComplexType(ctxt, node);
6529 }
6530 if (type->attributes != NULL) {
6531 xmlSchemaValidateAttributes(ctxt, node,
6532 type->attributes);
6533 }
6534 ctxt->type = type;
6535 break;
6536 }
6537 default:
6538 TODO xmlGenericError(xmlGenericErrorContext,
6539 "unimplemented content type %d\n",
6540 type->contentType);
6541 }
6542 return (ctxt->err);
6543 }
6544
6545 /**
6546 * xmlSchemaValidateContent:
6547 * @param ctxt a schema validation context
6548 * @param elem an element
6549 * @param type the type declaration
6550 *
6551 * Validate the content of an element against the type.
6552 *
6553 * Returns 0 if the element is schemas valid, a positive error code
6554 * number otherwise and -1 in case of internal or API error.
6555 */
6556 static int
xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node)6557 xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6558 {
6559 xmlNodePtr child;
6560 xmlSchemaTypePtr type;
6561
6562 child = ctxt->node;
6563 type = ctxt->type;
6564 ctxt->cur = node;
6565
6566 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6567 ctxt->cur = node;
6568
6569 switch (type->type) {
6570 case XML_SCHEMA_TYPE_ANY:
6571 /* Any type will do it, fine */
6572 TODO /* handle recursivity */
6573 break;
6574 case XML_SCHEMA_TYPE_COMPLEX:
6575 xmlSchemaValidateComplexType(ctxt, node);
6576 break;
6577 case XML_SCHEMA_TYPE_ELEMENT:{
6578 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
6579
6580 /*
6581 * Handle element reference here
6582 */
6583 if (decl->ref != NULL) {
6584 if (decl->refDecl == NULL) {
6585 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6586 "Internal error: element reference %s "
6587 "not resolved\n", decl->ref, NULL);
6588 return (-1);
6589 }
6590 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
6591 decl = decl->refDecl;
6592 }
6593
6594 xmlSchemaValidateElementType(ctxt, node);
6595 ctxt->type = type;
6596 break;
6597 }
6598 case XML_SCHEMA_TYPE_BASIC:
6599 xmlSchemaValidateBasicType(ctxt, node);
6600 break;
6601 case XML_SCHEMA_TYPE_FACET:
6602 TODO break;
6603 case XML_SCHEMA_TYPE_SIMPLE:
6604 xmlSchemaValidateSimpleType(ctxt, node);
6605 break;
6606 case XML_SCHEMA_TYPE_SEQUENCE:
6607 TODO break;
6608 case XML_SCHEMA_TYPE_CHOICE:
6609 TODO break;
6610 case XML_SCHEMA_TYPE_ALL:
6611 TODO break;
6612 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
6613 TODO break;
6614 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
6615 TODO break;
6616 case XML_SCHEMA_TYPE_UR:
6617 TODO break;
6618 case XML_SCHEMA_TYPE_RESTRICTION:
6619 /*xmlSchemaValidateRestrictionType(ctxt, node); */
6620 TODO break;
6621 case XML_SCHEMA_TYPE_EXTENSION:
6622 TODO break;
6623 case XML_SCHEMA_TYPE_ATTRIBUTE:
6624 TODO break;
6625 case XML_SCHEMA_TYPE_GROUP:
6626 TODO break;
6627 case XML_SCHEMA_TYPE_NOTATION:
6628 TODO break;
6629 case XML_SCHEMA_TYPE_LIST:
6630 TODO break;
6631 case XML_SCHEMA_TYPE_UNION:
6632 TODO break;
6633 case XML_SCHEMA_FACET_MININCLUSIVE:
6634 TODO break;
6635 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6636 TODO break;
6637 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6638 TODO break;
6639 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
6640 TODO break;
6641 case XML_SCHEMA_FACET_TOTALDIGITS:
6642 TODO break;
6643 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6644 TODO break;
6645 case XML_SCHEMA_FACET_PATTERN:
6646 TODO break;
6647 case XML_SCHEMA_FACET_ENUMERATION:
6648 TODO break;
6649 case XML_SCHEMA_FACET_WHITESPACE:
6650 TODO break;
6651 case XML_SCHEMA_FACET_LENGTH:
6652 TODO break;
6653 case XML_SCHEMA_FACET_MAXLENGTH:
6654 TODO break;
6655 case XML_SCHEMA_FACET_MINLENGTH:
6656 TODO break;
6657 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
6658 TODO break;
6659 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6660 TODO break;
6661 }
6662 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6663
6664 if (ctxt->node == NULL)
6665 return (ctxt->err);
6666 ctxt->node = ctxt->node->next;
6667 ctxt->type = type->next;
6668 return (ctxt->err);
6669 }
6670
6671 /**
6672 * xmlSchemaValidateType:
6673 * @param ctxt a schema validation context
6674 * @param elem an element
6675 * @param type the list of type declarations
6676 *
6677 * Validate the content of an element against the types.
6678 *
6679 * Returns 0 if the element is schemas valid, a positive error code
6680 * number otherwise and -1 in case of internal or API error.
6681 */
6682 static int
xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem,xmlSchemaElementPtr elemDecl,xmlSchemaTypePtr type)6683 xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
6684 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
6685 {
6686 xmlChar *nil;
6687
6688 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
6689 return (0);
6690
6691 /*
6692 * 3.3.4 : 2
6693 */
6694 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
6695 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
6696 "Element declaration %s is abstract\n",
6697 elemDecl->name, NULL);
6698 /* Changed, since the element declaration is abstract and not
6699 * the element itself. */
6700 /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
6701 "Element %s is abstract\n", elem->name, NULL); */
6702 return (ctxt->err);
6703 }
6704 /*
6705 * 3.3.4: 3
6706 */
6707 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
6708 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
6709 /* 3.3.4: 3.2 */
6710 if (xmlStrEqual(nil, BAD_CAST "true")) {
6711 if (elem->children != NULL) {
6712 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
6713 "Element %s is not empty\n", elem->name, NULL);
6714 return (ctxt->err);
6715 }
6716 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
6717 (elemDecl->value != NULL)) {
6718 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
6719 "Empty element %s cannot get a fixed value\n",
6720 elem->name, NULL);
6721 return (ctxt->err);
6722 }
6723 }
6724 } else {
6725 /* 3.3.4: 3.1 */
6726 if (nil != NULL) {
6727 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
6728 "Element %s with xs:nil but not nillable\n",
6729 elem->name, NULL);
6730 xmlFree(nil);
6731 return (ctxt->err);
6732 }
6733 }
6734
6735
6736
6737 ctxt->type = elemDecl->subtypes;
6738 ctxt->node = elem->children;
6739 xmlSchemaValidateContent(ctxt, elem);
6740 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6741
6742 return (ctxt->err);
6743 }
6744
6745
6746 /**
6747 * xmlSchemaValidateAttributes:
6748 * @param ctxt a schema validation context
6749 * @param elem an element
6750 * @param attributes the list of attribute declarations
6751 *
6752 * Validate the attributes of an element.
6753 *
6754 * Returns 0 if the element is schemas valid, a positive error code
6755 * number otherwise and -1 in case of internal or API error.
6756 */
6757 static int
xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem,xmlSchemaAttributePtr attributes)6758 xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
6759 xmlSchemaAttributePtr attributes)
6760 {
6761 int i, ret;
6762 xmlAttrPtr attr;
6763 xmlChar *value;
6764 xmlSchemaAttributeGroupPtr group = NULL;
6765 int found;
6766
6767 if (attributes == NULL)
6768 return (0);
6769 while (attributes != NULL) {
6770 found = 0;
6771 /*
6772 * Handle attribute groups
6773 */
6774 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6775 group = (xmlSchemaAttributeGroupPtr) attributes;
6776 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6777 attributes = group->next;
6778 continue;
6779 }
6780 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6781 attr = ctxt->attr[i].attr;
6782 if (attr == NULL)
6783 continue;
6784 if (attributes->ref != NULL) {
6785 if (!xmlStrEqual(attr->name, attributes->ref))
6786 continue;
6787 if (attr->ns != NULL) {
6788 if ((attributes->refNs == NULL) ||
6789 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6790 continue;
6791 } else if (attributes->refNs != NULL) {
6792 continue;
6793 }
6794 } else {
6795 if (!xmlStrEqual(attr->name, attributes->name))
6796 continue;
6797 /*
6798 * handle the namespaces checks here
6799 */
6800 if (attr->ns == NULL) {
6801 /*
6802 * accept an unqualified attribute only if the target
6803 * namespace of the declaration is absent.
6804 */
6805 if (attributes->targetNamespace != NULL)
6806 /*
6807 * This check was removed, since the target namespace
6808 * was evaluated during parsing and already took
6809 * "attributeFormDefault" into account.
6810 */
6811 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
6812 continue;
6813 } else {
6814 if (attributes->targetNamespace == NULL)
6815 continue;
6816 if (!xmlStrEqual(attributes->targetNamespace,
6817 attr->ns->href))
6818 continue;
6819 }
6820 }
6821 found = 1;
6822 ctxt->cur = (xmlNodePtr) attributes;
6823
6824 if (attributes->subtypes == NULL) {
6825 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
6826 "Internal error: attribute %s type not resolved\n",
6827 attr->name, NULL);
6828 continue;
6829 }
6830
6831 if (attributes->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6832 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INVALIDATTR,
6833 "attribute %s on %s is prohibited\n",
6834 attributes->name, elem->name);
6835 /* Setting the state to XML_SCHEMAS_ATTR_CHECKED seems
6836 * not very logical but it suppresses the
6837 * "attribute is unknown" error report. Please change
6838 * this if you know better */
6839 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6840 break;
6841 }
6842
6843 value = xmlNodeListGetString(elem->doc, attr->children, 1);
6844 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6845 value);
6846 if (ret != 0) {
6847 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
6848 XML_SCHEMAS_ERR_ATTRINVALID,
6849 "attribute %s on %s does not match type\n",
6850 attr->name, elem->name);
6851 } else {
6852 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6853 }
6854 if (value != NULL) {
6855 xmlFree(value);
6856 }
6857 }
6858 if ((!found) && (attributes->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6859 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_MISSING,
6860 "required attribute %s on %s is missing\n",
6861 attributes->name, elem->name);
6862 }
6863 attributes = attributes->next;
6864 }
6865 return (ctxt->err);
6866 }
6867
6868 /**
6869 * xmlSchemaValidateElement:
6870 * @param ctxt a schema validation context
6871 * @param elem an element
6872 *
6873 * Validate an element in a tree
6874 *
6875 * Returns 0 if the element is schemas valid, a positive error code
6876 * number otherwise and -1 in case of internal or API error.
6877 */
6878 static int
xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)6879 xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6880 {
6881 xmlSchemaElementPtr elemDecl;
6882 int ret, attrBase;
6883
6884 if (elem->ns != NULL) {
6885 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6886 elem->name, elem->ns->href, NULL);
6887 } else {
6888 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6889 elem->name, NULL, NULL);
6890 }
6891 /*
6892 * special case whe elementFormDefault is unqualified for top-level elem.
6893 */
6894 /*
6895 * This was removed, since elementFormDefault does not apply to top-level
6896 * element declarations.
6897 */
6898 /*
6899 if ((elemDecl == NULL) && (elem->ns != NULL) &&
6900 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6901 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6902 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6903 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6904 elem->name, NULL, NULL);
6905 }
6906 */
6907
6908 /*
6909 * 3.3.4 : 1
6910 */
6911 if (elemDecl == NULL) {
6912 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
6913 "Element %s not declared\n", elem->name, NULL);
6914 return (ctxt->err);
6915 }
6916 if (elemDecl->subtypes == NULL) {
6917 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
6918 "Element %s has no type\n", elem->name, NULL);
6919 return (ctxt->err);
6920 }
6921 /*
6922 * Verify the attributes
6923 */
6924 attrBase = ctxt->attrBase;
6925 ctxt->attrBase = ctxt->attrNr;
6926 xmlSchemaRegisterAttributes(ctxt, elem->properties);
6927 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6928 /*
6929 * Verify the element content recursively
6930 */
6931 if (elemDecl->contModel != NULL) {
6932 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6933 (xmlRegExecCallbacks)
6934 xmlSchemaValidateCallback, ctxt);
6935 #ifdef DEBUG_AUTOMATA
6936 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
6937 #endif
6938 }
6939 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
6940 if (elemDecl->contModel != NULL) {
6941 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
6942 #ifdef DEBUG_AUTOMATA
6943 xmlGenericError(xmlGenericErrorContext,
6944 "====> %s : %d\n", elem->name, ret);
6945 #endif
6946 if (ret == 0) {
6947 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
6948 "Element %s content check failed\n",
6949 elem->name, NULL);
6950 } else if (ret < 0) {
6951 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
6952 "Element %s content check failed\n",
6953 elem->name, NULL);
6954 #ifdef DEBUG_CONTENT
6955 } else {
6956 xmlGenericError(xmlGenericErrorContext,
6957 "Element %s content check succeeded\n",
6958 elem->name);
6959
6960 #endif
6961 }
6962 xmlRegFreeExecCtxt(ctxt->regexp);
6963 }
6964 /*
6965 * Verify that all attributes were Schemas-validated
6966 */
6967 xmlSchemaCheckAttributes(ctxt, elem);
6968 ctxt->attrNr = ctxt->attrBase;
6969 ctxt->attrBase = attrBase;
6970
6971 return (ctxt->err);
6972 }
6973
6974 /**
6975 * xmlSchemaValidateDocument:
6976 * @param ctxt a schema validation context
6977 * @param doc a parsed document tree
6978 *
6979 * Validate a document tree in memory.
6980 *
6981 * Returns 0 if the document is schemas valid, a positive error code
6982 * number otherwise and -1 in case of internal or API error.
6983 */
6984 static int
xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)6985 xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6986 {
6987 xmlNodePtr root;
6988 xmlSchemaElementPtr elemDecl;
6989
6990 root = xmlDocGetRootElement(doc);
6991 if (root == NULL) {
6992 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
6993 "document has no root\n", NULL, NULL);
6994 return (ctxt->err);
6995 }
6996
6997 if (root->ns != NULL)
6998 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6999 root->name, root->ns->href, NULL);
7000 else
7001 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
7002 root->name, NULL, NULL);
7003 /*
7004 * special case whe elementFormDefault is unqualified for top-level elem.
7005 */
7006 if ((elemDecl == NULL) && (root->ns != NULL) &&
7007 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
7008 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
7009 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
7010 root->name, NULL, NULL);
7011 }
7012
7013 if (elemDecl == NULL) {
7014 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
7015 "Element %s not declared\n", root->name, NULL);
7016 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
7017 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
7018 "Root element %s not toplevel\n", root->name, NULL);
7019 }
7020 /*
7021 * Okay, start the recursive validation
7022 */
7023 xmlSchemaValidateElement(ctxt, root);
7024
7025 return (ctxt->err);
7026 }
7027
7028 /************************************************************************
7029 * *
7030 * SAX Validation code *
7031 * *
7032 ************************************************************************/
7033
7034 /************************************************************************
7035 * *
7036 * Validation interfaces *
7037 * *
7038 ************************************************************************/
7039
7040 /**
7041 * xmlSchemaNewValidCtxt:
7042 * @param schema a precompiled XML Schemas
7043 *
7044 * Create an XML Schemas validation context based on the given schema
7045 *
7046 * Returns the validation context or NULL in case of error
7047 */
7048 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)7049 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
7050 {
7051 xmlSchemaValidCtxtPtr ret;
7052
7053 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
7054 if (ret == NULL) {
7055 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
7056 return (NULL);
7057 }
7058 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
7059 ret->schema = schema;
7060 ret->attrNr = 0;
7061 ret->attrMax = 10;
7062 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
7063 sizeof
7064 (xmlSchemaAttrState));
7065 if (ret->attr == NULL) {
7066 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
7067 free(ret);
7068 return (NULL);
7069 }
7070 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
7071 return (ret);
7072 }
7073
7074 /**
7075 * xmlSchemaFreeValidCtxt:
7076 * @param ctxt the schema validation context
7077 *
7078 * Free the resources associated to the schema validation context
7079 */
7080 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)7081 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
7082 {
7083 if (ctxt == NULL)
7084 return;
7085 if (ctxt->attr != NULL)
7086 xmlFree(ctxt->attr);
7087 if (ctxt->value != NULL)
7088 xmlSchemaFreeValue(ctxt->value);
7089 xmlFree(ctxt);
7090 }
7091
7092 /**
7093 * xmlSchemaSetValidErrors:
7094 * @param ctxt a schema validation context
7095 * @param err the error function
7096 * @param warn the warning function
7097 * @param ctx the functions context
7098 *
7099 * Set the error and warning callback informations
7100 */
7101 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)7102 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
7103 xmlSchemaValidityErrorFunc err,
7104 xmlSchemaValidityWarningFunc warn, void *ctx)
7105 {
7106 if (ctxt == NULL)
7107 return;
7108 ctxt->error = err;
7109 ctxt->warning = warn;
7110 ctxt->userData = ctx;
7111 }
7112
7113 /**
7114 * xmlSchemaValidateDoc:
7115 * @param ctxt a schema validation context
7116 * @param doc a parsed document tree
7117 *
7118 * Validate a document tree in memory.
7119 *
7120 * Returns 0 if the document is schemas valid, a positive error code
7121 * number otherwise and -1 in case of internal or API error.
7122 */
7123 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)7124 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
7125 {
7126 int ret;
7127
7128 if ((ctxt == NULL) || (doc == NULL))
7129 return (-1);
7130
7131 ctxt->doc = doc;
7132 ret = xmlSchemaValidateDocument(ctxt, doc);
7133 return (ret);
7134 }
7135
7136 /**
7137 * xmlSchemaValidateStream:
7138 * @param ctxt a schema validation context
7139 * @param input the input to use for reading the data
7140 * @param enc an optional encoding information
7141 * @param sax a SAX handler for the resulting events
7142 * @param user_data the context to provide to the SAX handler.
7143 *
7144 * Validate a document tree in memory.
7145 *
7146 * Returns 0 if the document is schemas valid, a positive error code
7147 * number otherwise and -1 in case of internal or API error.
7148 */
7149 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,xmlSAXHandlerPtr sax,void * user_data)7150 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
7151 xmlParserInputBufferPtr input, xmlCharEncoding enc,
7152 xmlSAXHandlerPtr sax, void *user_data)
7153 {
7154 if ((ctxt == NULL) || (input == NULL))
7155 return (-1);
7156 ctxt->input = input;
7157 ctxt->enc = enc;
7158 ctxt->sax = sax;
7159 ctxt->user_data = user_data;
7160 TODO return (0);
7161 }
7162
7163 #endif /* LIBXML_SCHEMAS_ENABLED */
7164