blob: e9dfadb2c3a72f7554e0bc0e8b883b3e23d5128c [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010/*
11 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
15 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016#define IN_LIBXML
17#include "libxml.h"
18
19#ifdef LIBXML_SCHEMAS_ENABLED
20
21#include <string.h>
22#include <libxml/xmlmemory.h>
23#include <libxml/parser.h>
24#include <libxml/parserInternals.h>
25#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000026#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000027
28#include <libxml/xmlschemas.h>
29#include <libxml/schemasInternals.h>
30#include <libxml/xmlschemastypes.h>
31#include <libxml/xmlautomata.h>
32#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000033#include <libxml/dict.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000034
Daniel Veillarda84c0b32003-06-02 16:58:46 +000035/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000036
Daniel Veillard82bbbd42003-05-11 20:16:09 +000037/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000038
Daniel Veillard82bbbd42003-05-11 20:16:09 +000039/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000040
Daniel Veillard118aed72002-09-24 14:13:13 +000041/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000042
Daniel Veillard4255d502002-04-16 15:50:10 +000043/* #define DEBUG_AUTOMATA 1 */
44
45#define UNBOUNDED (1 << 30)
46#define TODO \
47 xmlGenericError(xmlGenericErrorContext, \
48 "Unimplemented block at %s:%d\n", \
49 __FILE__, __LINE__);
50
Daniel Veillard5a872412002-05-22 06:40:27 +000051#define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
52
Daniel Veillard4255d502002-04-16 15:50:10 +000053/*
54 * The XML Schemas namespaces
55 */
56static const xmlChar *xmlSchemaNs = (const xmlChar *)
57 "http://www.w3.org/2001/XMLSchema";
58
59static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
60 "http://www.w3.org/2001/XMLSchema-instance";
61
62#define IS_SCHEMA(node, type) \
63 ((node != NULL) && (node->ns != NULL) && \
64 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
65 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
66
67#define XML_SCHEMAS_PARSE_ERROR 1
68
Daniel Veillardbd2904b2003-11-25 15:38:59 +000069#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
70
Daniel Veillard4255d502002-04-16 15:50:10 +000071struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000072 void *userData; /* user specific data block */
73 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
74 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +000075 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000076 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +000077 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +000078
Daniel Veillardbe9c6322003-11-22 20:37:51 +000079 xmlSchemaPtr topschema; /* The main schema */
80 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
81
Daniel Veillardd0c9c322003-10-10 00:49:42 +000082 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000083 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +000084 int counter;
85
Daniel Veillardbe9c6322003-11-22 20:37:51 +000086 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000087 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000088 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +000089
Daniel Veillardd0c9c322003-10-10 00:49:42 +000090 const char *buffer;
91 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +000092
Daniel Veillard4255d502002-04-16 15:50:10 +000093 /*
94 * Used to build complex element content models
95 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000096 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +000097 xmlAutomataStatePtr start;
98 xmlAutomataStatePtr end;
99 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000100
101 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000102 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard4255d502002-04-16 15:50:10 +0000103};
104
105
106#define XML_SCHEMAS_ATTR_UNKNOWN 1
107#define XML_SCHEMAS_ATTR_CHECKED 2
108
109typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
110typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
111struct _xmlSchemaAttrState {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000112 xmlAttrPtr attr;
113 int state;
Daniel Veillard4255d502002-04-16 15:50:10 +0000114};
115
116/**
117 * xmlSchemaValidCtxt:
118 *
119 * A Schemas validation context
120 */
121
122struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000123 void *userData; /* user specific data block */
124 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
125 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000126 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000127
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000128 xmlSchemaPtr schema; /* The schema in use */
129 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000130 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000131 xmlCharEncoding enc;
132 xmlSAXHandlerPtr sax;
133 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000134
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000135 xmlDocPtr myDoc;
136 int err;
137 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000138
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000139 xmlNodePtr node;
140 xmlNodePtr cur;
141 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000142
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000143 xmlRegExecCtxtPtr regexp;
144 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000145
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000146 int attrNr;
147 int attrBase;
148 int attrMax;
149 xmlSchemaAttrStatePtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +0000150};
151
Daniel Veillard1d913862003-11-21 00:28:39 +0000152/*
153 * These are the entries in the schemas importSchemas hash table
154 */
155typedef struct _xmlSchemaImport xmlSchemaImport;
156typedef xmlSchemaImport *xmlSchemaImportPtr;
157struct _xmlSchemaImport {
158 const xmlChar *schemaLocation;
159 xmlSchemaPtr schema;
160};
Daniel Veillard4255d502002-04-16 15:50:10 +0000161
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000162/*
163 * These are the entries associated to includes in a schemas
164 */
165typedef struct _xmlSchemaInclude xmlSchemaInclude;
166typedef xmlSchemaInclude *xmlSchemaIncludePtr;
167struct _xmlSchemaInclude {
168 xmlSchemaIncludePtr next;
169
170 const xmlChar *schemaLocation;
171 xmlDocPtr doc;
172};
173
Daniel Veillard4255d502002-04-16 15:50:10 +0000174/************************************************************************
175 * *
176 * Some predeclarations *
177 * *
178 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000179static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
180 xmlSchemaTypePtr type,
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000181 const xmlChar * value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000182
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000183static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
184 xmlSchemaPtr schema,
185 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +0000186static int
187xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
188 xmlSchemaTypePtr type,
189 const xmlChar * value,
190 int fireErrors);
191
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000192/************************************************************************
193 * *
194 * Datatype error handlers *
195 * *
196 ************************************************************************/
197
198/**
199 * xmlSchemaPErrMemory:
200 * @node: a context node
201 * @extra: extra informations
202 *
203 * Handle an out of memory condition
204 */
205static void
206xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
207 const char *extra, xmlNodePtr node)
208{
209 if (ctxt != NULL)
210 ctxt->nberrors++;
211 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
212 extra);
213}
214
215/**
216 * xmlSchemaPErr:
217 * @ctxt: the parsing context
218 * @node: the context node
219 * @error: the error code
220 * @msg: the error message
221 * @str1: extra data
222 * @str2: extra data
223 *
224 * Handle a parser error
225 */
226static void
227xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
228 const char *msg, const xmlChar * str1, const xmlChar * str2)
229{
230 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000231 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000232 void *data = NULL;
233
234 if (ctxt != NULL) {
235 ctxt->nberrors++;
236 channel = ctxt->error;
237 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000238 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000239 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000240 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000241 error, XML_ERR_ERROR, NULL, 0,
242 (const char *) str1, (const char *) str2, NULL, 0, 0,
243 msg, str1, str2);
244}
245
246/**
247 * xmlSchemaPErr2:
248 * @ctxt: the parsing context
249 * @node: the context node
250 * @node: the current child
251 * @error: the error code
252 * @msg: the error message
253 * @str1: extra data
254 * @str2: extra data
255 *
256 * Handle a parser error
257 */
258static void
259xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
260 xmlNodePtr child, int error,
261 const char *msg, const xmlChar * str1, const xmlChar * str2)
262{
263 if (child != NULL)
264 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
265 else
266 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
267}
268
269/**
270 * xmlSchemaVTypeErrMemory:
271 * @node: a context node
272 * @extra: extra informations
273 *
274 * Handle an out of memory condition
275 */
276static void
277xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
278 const char *extra, xmlNodePtr node)
279{
280 if (ctxt != NULL) {
281 ctxt->nberrors++;
282 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
283 }
284 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
285 extra);
286}
287
288/**
289 * xmlSchemaVErr3:
290 * @ctxt: the validation context
291 * @node: the context node
292 * @error: the error code
293 * @msg: the error message
294 * @str1: extra data
295 * @str2: extra data
296 * @str3: extra data
297 *
298 * Handle a validation error
299 */
300static void
301xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
302 const char *msg, const xmlChar *str1, const xmlChar *str2,
303 const xmlChar *str3)
304{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000305 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000306 xmlGenericErrorFunc channel = NULL;
307 void *data = NULL;
308
309 if (ctxt != NULL) {
310 ctxt->nberrors++;
311 ctxt->err = error;
312 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000313 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000314 data = ctxt->userData;
315 }
316 /* reajust to global error numbers */
317 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000318 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000319 error, XML_ERR_ERROR, NULL, 0,
320 (const char *) str1, (const char *) str2,
321 (const char *) str3, 0, 0,
322 msg, str1, str2, str3);
323}
324/**
325 * xmlSchemaVErr:
326 * @ctxt: the validation context
327 * @node: the context node
328 * @error: the error code
329 * @msg: the error message
330 * @str1: extra data
331 * @str2: extra data
332 *
333 * Handle a validation error
334 */
335static void
336xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
337 const char *msg, const xmlChar * str1, const xmlChar * str2)
338{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000339 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000340 xmlGenericErrorFunc channel = NULL;
341 void *data = NULL;
342
343 if (ctxt != NULL) {
344 ctxt->nberrors++;
345 ctxt->err = error;
346 channel = ctxt->error;
347 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000348 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000349 }
350 /* reajust to global error numbers */
351 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000352 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000353 error, XML_ERR_ERROR, NULL, 0,
354 (const char *) str1, (const char *) str2, NULL, 0, 0,
355 msg, str1, str2);
356}
Daniel Veillard4255d502002-04-16 15:50:10 +0000357
358/************************************************************************
359 * *
360 * Allocation functions *
361 * *
362 ************************************************************************/
363
364/**
365 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +0000366 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000367 *
368 * Allocate a new Schema structure.
369 *
370 * Returns the newly allocated structure or NULL in case or error
371 */
372static xmlSchemaPtr
373xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
374{
375 xmlSchemaPtr ret;
376
377 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
378 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000379 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000380 return (NULL);
381 }
382 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000383 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000384 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000385
386 return (ret);
387}
388
389/**
390 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000391 *
392 * Allocate a new Facet structure.
393 *
394 * Returns the newly allocated structure or NULL in case or error
395 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000396xmlSchemaFacetPtr
397xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000398{
399 xmlSchemaFacetPtr ret;
400
401 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
402 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000403 return (NULL);
404 }
405 memset(ret, 0, sizeof(xmlSchemaFacet));
406
407 return (ret);
408}
409
410/**
411 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +0000412 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000413 * @node: a node
414 *
415 * Allocate a new annotation structure.
416 *
417 * Returns the newly allocated structure or NULL in case or error
418 */
419static xmlSchemaAnnotPtr
420xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
421{
422 xmlSchemaAnnotPtr ret;
423
424 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
425 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000426 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000427 return (NULL);
428 }
429 memset(ret, 0, sizeof(xmlSchemaAnnot));
430 ret->content = node;
431 return (ret);
432}
433
434/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000435 * xmlSchemaFreeAnnot:
436 * @annot: a schema type structure
437 *
438 * Deallocate a annotation structure
439 */
440static void
441xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
442{
443 if (annot == NULL)
444 return;
445 xmlFree(annot);
446}
447
448/**
Daniel Veillard1d913862003-11-21 00:28:39 +0000449 * xmlSchemaFreeImport:
450 * @import: a schema import structure
451 *
452 * Deallocate an import structure
453 */
454static void
455xmlSchemaFreeImport(xmlSchemaImportPtr import)
456{
457 if (import == NULL)
458 return;
459
460 xmlSchemaFree(import->schema);
Daniel Veillard1d913862003-11-21 00:28:39 +0000461 xmlFree(import);
462}
463
464/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000465 * xmlSchemaFreeInclude:
466 * @include: a schema include structure
467 *
468 * Deallocate an include structure
469 */
470static void
471xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
472{
473 if (include == NULL)
474 return;
475
476 xmlFreeDoc(include->doc);
477 xmlFree(include);
478}
479
480/**
481 * xmlSchemaFreeIncludeList:
482 * @includes: a schema include list
483 *
484 * Deallocate an include structure
485 */
486static void
487xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
488{
489 xmlSchemaIncludePtr next;
490
491 while (includes != NULL) {
492 next = includes->next;
493 xmlSchemaFreeInclude(includes);
494 includes = next;
495 }
496}
497
498/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000499 * xmlSchemaFreeNotation:
500 * @schema: a schema notation structure
501 *
502 * Deallocate a Schema Notation structure.
503 */
504static void
505xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
506{
507 if (nota == NULL)
508 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000509 xmlFree(nota);
510}
511
512/**
513 * xmlSchemaFreeAttribute:
514 * @schema: a schema attribute structure
515 *
516 * Deallocate a Schema Attribute structure.
517 */
518static void
519xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
520{
521 if (attr == NULL)
522 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000523 xmlFree(attr);
524}
525
526/**
527 * xmlSchemaFreeAttributeGroup:
528 * @schema: a schema attribute group structure
529 *
530 * Deallocate a Schema Attribute Group structure.
531 */
532static void
533xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
534{
535 if (attr == NULL)
536 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000537 xmlFree(attr);
538}
539
540/**
541 * xmlSchemaFreeElement:
542 * @schema: a schema element structure
543 *
544 * Deallocate a Schema Element structure.
545 */
546static void
547xmlSchemaFreeElement(xmlSchemaElementPtr elem)
548{
549 if (elem == NULL)
550 return;
Daniel Veillard32370232002-10-16 14:08:14 +0000551 if (elem->annot != NULL)
552 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000553 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000554 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000555 xmlFree(elem);
556}
557
558/**
559 * xmlSchemaFreeFacet:
560 * @facet: a schema facet structure
561 *
562 * Deallocate a Schema Facet structure.
563 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000564void
Daniel Veillard4255d502002-04-16 15:50:10 +0000565xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
566{
567 if (facet == NULL)
568 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000569 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000570 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000571 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000572 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000573 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000574 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000575 xmlFree(facet);
576}
577
578/**
579 * xmlSchemaFreeType:
580 * @type: a schema type structure
581 *
582 * Deallocate a Schema Type structure.
583 */
584void
585xmlSchemaFreeType(xmlSchemaTypePtr type)
586{
587 if (type == NULL)
588 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000589 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000590 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000591 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000592 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000593
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000594 facet = type->facets;
595 while (facet != NULL) {
596 next = facet->next;
597 xmlSchemaFreeFacet(facet);
598 facet = next;
599 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000600 }
601 xmlFree(type);
602}
603
604/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000605 * xmlSchemaFreeTypeList:
606 * @type: a schema type structure
607 *
608 * Deallocate a Schema Type structure.
609 */
610static void
611xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
612{
613 xmlSchemaTypePtr next;
614
615 while (type != NULL) {
616 next = type->redef;
617 xmlSchemaFreeType(type);
618 type = next;
619 }
620}
621
622/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000623 * xmlSchemaFree:
624 * @schema: a schema structure
625 *
626 * Deallocate a Schema structure.
627 */
628void
629xmlSchemaFree(xmlSchemaPtr schema)
630{
631 if (schema == NULL)
632 return;
633
Daniel Veillard4255d502002-04-16 15:50:10 +0000634 if (schema->notaDecl != NULL)
635 xmlHashFree(schema->notaDecl,
636 (xmlHashDeallocator) xmlSchemaFreeNotation);
637 if (schema->attrDecl != NULL)
638 xmlHashFree(schema->attrDecl,
639 (xmlHashDeallocator) xmlSchemaFreeAttribute);
640 if (schema->attrgrpDecl != NULL)
641 xmlHashFree(schema->attrgrpDecl,
642 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
643 if (schema->elemDecl != NULL)
644 xmlHashFree(schema->elemDecl,
645 (xmlHashDeallocator) xmlSchemaFreeElement);
646 if (schema->typeDecl != NULL)
647 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000648 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000649 if (schema->groupDecl != NULL)
650 xmlHashFree(schema->groupDecl,
651 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +0000652 if (schema->schemasImports != NULL)
653 xmlHashFree(schema->schemasImports,
654 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000655 if (schema->includes != NULL) {
656 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
657 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000658 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000659 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +0000660 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000661 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000662 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000663
664 xmlFree(schema);
665}
666
667/************************************************************************
668 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000669 * Debug functions *
670 * *
671 ************************************************************************/
672
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000673#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000674
Daniel Veillard4255d502002-04-16 15:50:10 +0000675/**
676 * xmlSchemaElementDump:
677 * @elem: an element
678 * @output: the file output
679 *
680 * Dump the element
681 */
682static void
683xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000684 const xmlChar * name ATTRIBUTE_UNUSED,
685 const xmlChar * context ATTRIBUTE_UNUSED,
686 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000687{
688 if (elem == NULL)
689 return;
690
691 fprintf(output, "Element ");
692 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000693 fprintf(output, "toplevel ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000694 fprintf(output, ": %s ", elem->name);
695 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000696 fprintf(output, "namespace '%s' ", namespace);
697
Daniel Veillard4255d502002-04-16 15:50:10 +0000698 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000699 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000700 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000701 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000702 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000703 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000704 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000705 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000706 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000707 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000708 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000709 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000710 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000711 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000712 fprintf(output, "\n");
713 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000714 fprintf(output, " ");
715 if (elem->minOccurs != 1)
716 fprintf(output, "min: %d ", elem->minOccurs);
717 if (elem->maxOccurs >= UNBOUNDED)
718 fprintf(output, "max: unbounded\n");
719 else if (elem->maxOccurs != 1)
720 fprintf(output, "max: %d\n", elem->maxOccurs);
721 else
722 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000723 }
724 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000725 fprintf(output, " type: %s", elem->namedType);
726 if (elem->namedTypeNs != NULL)
727 fprintf(output, " ns %s\n", elem->namedTypeNs);
728 else
729 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000730 }
731 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000732 fprintf(output, " substitutionGroup: %s", elem->substGroup);
733 if (elem->substGroupNs != NULL)
734 fprintf(output, " ns %s\n", elem->substGroupNs);
735 else
736 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000737 }
738 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000739 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000740}
741
742/**
743 * xmlSchemaAnnotDump:
744 * @output: the file output
745 * @annot: a annotation
746 *
747 * Dump the annotation
748 */
749static void
750xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
751{
752 xmlChar *content;
753
754 if (annot == NULL)
755 return;
756
757 content = xmlNodeGetContent(annot->content);
758 if (content != NULL) {
759 fprintf(output, " Annot: %s\n", content);
760 xmlFree(content);
761 } else
762 fprintf(output, " Annot: empty\n");
763}
764
765/**
766 * xmlSchemaTypeDump:
767 * @output: the file output
768 * @type: a type structure
769 *
770 * Dump a SchemaType structure
771 */
772static void
773xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
774{
775 if (type == NULL) {
776 fprintf(output, "Type: NULL\n");
777 return;
778 }
779 fprintf(output, "Type: ");
780 if (type->name != NULL)
781 fprintf(output, "%s, ", type->name);
782 else
783 fprintf(output, "no name");
784 switch (type->type) {
785 case XML_SCHEMA_TYPE_BASIC:
786 fprintf(output, "basic ");
787 break;
788 case XML_SCHEMA_TYPE_SIMPLE:
789 fprintf(output, "simple ");
790 break;
791 case XML_SCHEMA_TYPE_COMPLEX:
792 fprintf(output, "complex ");
793 break;
794 case XML_SCHEMA_TYPE_SEQUENCE:
795 fprintf(output, "sequence ");
796 break;
797 case XML_SCHEMA_TYPE_CHOICE:
798 fprintf(output, "choice ");
799 break;
800 case XML_SCHEMA_TYPE_ALL:
801 fprintf(output, "all ");
802 break;
803 case XML_SCHEMA_TYPE_UR:
804 fprintf(output, "ur ");
805 break;
806 case XML_SCHEMA_TYPE_RESTRICTION:
807 fprintf(output, "restriction ");
808 break;
809 case XML_SCHEMA_TYPE_EXTENSION:
810 fprintf(output, "extension ");
811 break;
812 default:
813 fprintf(output, "unknowntype%d ", type->type);
814 break;
815 }
816 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000817 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000818 }
819 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000820 case XML_SCHEMA_CONTENT_UNKNOWN:
821 fprintf(output, "unknown ");
822 break;
823 case XML_SCHEMA_CONTENT_EMPTY:
824 fprintf(output, "empty ");
825 break;
826 case XML_SCHEMA_CONTENT_ELEMENTS:
827 fprintf(output, "element ");
828 break;
829 case XML_SCHEMA_CONTENT_MIXED:
830 fprintf(output, "mixed ");
831 break;
832 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
833 fprintf(output, "mixed_or_elems ");
834 break;
835 case XML_SCHEMA_CONTENT_BASIC:
836 fprintf(output, "basic ");
837 break;
838 case XML_SCHEMA_CONTENT_SIMPLE:
839 fprintf(output, "simple ");
840 break;
841 case XML_SCHEMA_CONTENT_ANY:
842 fprintf(output, "any ");
843 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000844 }
845 fprintf(output, "\n");
846 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000847 fprintf(output, " ");
848 if (type->minOccurs != 1)
849 fprintf(output, "min: %d ", type->minOccurs);
850 if (type->maxOccurs >= UNBOUNDED)
851 fprintf(output, "max: unbounded\n");
852 else if (type->maxOccurs != 1)
853 fprintf(output, "max: %d\n", type->maxOccurs);
854 else
855 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000856 }
857 if (type->annot != NULL)
858 xmlSchemaAnnotDump(output, type->annot);
859 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000860 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000861
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000862 fprintf(output, " subtypes: ");
863 while (sub != NULL) {
864 fprintf(output, "%s ", sub->name);
865 sub = sub->next;
866 }
867 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000868 }
869
870}
871
872/**
873 * xmlSchemaDump:
874 * @output: the file output
875 * @schema: a schema structure
876 *
877 * Dump a Schema structure.
878 */
879void
880xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
881{
882 if (schema == NULL) {
883 fprintf(output, "Schemas: NULL\n");
884 return;
885 }
886 fprintf(output, "Schemas: ");
887 if (schema->name != NULL)
888 fprintf(output, "%s, ", schema->name);
889 else
890 fprintf(output, "no name, ");
891 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +0000892 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000893 else
894 fprintf(output, "no target namespace");
895 fprintf(output, "\n");
896 if (schema->annot != NULL)
897 xmlSchemaAnnotDump(output, schema->annot);
898
899 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
900 output);
901 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000902 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +0000903}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000904#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +0000905
906/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000907 * *
908 * Utilities *
909 * *
910 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000911
912/**
913 * xmlSchemaGetProp:
914 * @ctxt: the parser context
915 * @node: the node
916 * @name: the property name
917 *
918 * Read a attribute value and internalize the string
919 *
920 * Returns the string or NULL if not present.
921 */
922static const xmlChar *
923xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
924 const char *name)
925{
926 xmlChar *val;
927 const xmlChar *ret;
928
929 val = xmlGetProp(node, BAD_CAST name);
930 if (val == NULL)
931 return(NULL);
932 ret = xmlDictLookup(ctxt->dict, val, -1);
933 xmlFree(val);
934 return(ret);
935}
936
William M. Brack29aa7722004-05-12 00:27:56 +0000937#if 0
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000938/**
939 * xmlSchemaGetNamespace:
940 * @ctxt: the parser context
941 * @schema: the schemas containing the declaration
942 * @node: the node
943 * @qname: the QName to analyze
944 *
945 * Find the namespace name for the given declaration.
946 *
947 * Returns the local name for that declaration, as well as the namespace name
William M. Bracke7091952004-05-11 15:09:58 +0000948 * NOTE: This function is no longer used (Buchcik, May '04)
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000949 */
950static const xmlChar *
951xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
952 xmlNodePtr node, const xmlChar *qname,
953 const xmlChar **namespace) {
954 int len;
955 const xmlChar *name, *prefix, *def = NULL;
956 xmlNsPtr ns;
957
958 *namespace = NULL;
959
William M. Bracke7091952004-05-11 15:09:58 +0000960 /* TODO: The following seems to be not correct here:
961 * 1. The name of a declaration is a NCName, not a QName.
962 * 2. The attribute "targetNamespace" is allowed for the
963 * <schema> Element Information Item only.
964 * 3. One cannot evaluate the target namespace, by the type
965 * of declaration, since it is dependant on the xxxFormDefault
966 * of <schema> and the form attribute of an <element> or <attribute>.
967 */
968
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000969 if (xmlStrEqual(node->name, BAD_CAST "element") ||
970 xmlStrEqual(node->name, BAD_CAST "attribute") ||
971 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
972 xmlStrEqual(node->name, BAD_CAST "complexType")) {
973 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
974 }
975
William M. Bracke7091952004-05-11 15:09:58 +0000976
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000977 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
978 name = xmlSplitQName3(qname, &len);
979 if (name == NULL) {
980 if (def == NULL) {
981 if (xmlStrEqual(node->name, BAD_CAST "element")) {
982 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
983 *namespace = schema->targetNamespace;
984 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
985 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
986 *namespace = schema->targetNamespace;
987 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
988 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
989 *namespace = schema->targetNamespace;
990 }
991 } else {
992 *namespace = def;
993 }
994 return(qname);
995 }
William M. Bracke7091952004-05-11 15:09:58 +0000996
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000997 name = xmlDictLookup(ctxt->dict, name, -1);
998 prefix = xmlDictLookup(ctxt->dict, qname, len);
999 if (def != NULL) {
1000 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
1001 "%s: presence of both prefix %s and targetNamespace\n",
1002 node->name, prefix);
1003 }
1004 ns = xmlSearchNs(node->doc, node, prefix);
1005 if (ns == NULL) {
1006 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1007 "%s: the QName prefix %s is undefined\n",
1008 node->name, prefix);
1009 return(name);
1010 }
1011 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1012 return(name);
1013}
William M. Brack29aa7722004-05-12 00:27:56 +00001014#endif
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001015
1016/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00001017 * *
1018 * Parsing functions *
1019 * *
1020 ************************************************************************/
1021
1022/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001023 * xmlSchemaGetElem:
1024 * @schema: the schemas context
1025 * @name: the element name
1026 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001027 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001028 *
1029 * Lookup a an element in the schemas or the accessible schemas
1030 *
1031 * Returns the element definition or NULL if not found.
1032 */
1033static xmlSchemaElementPtr
1034xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001035 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001036{
1037 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001038 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001039
1040 if ((name == NULL) || (schema == NULL))
1041 return (NULL);
1042
1043 if (namespace == NULL) {
1044 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001045 if ((ret != NULL) &&
1046 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001047 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001048 }
William M. Bracke7091952004-05-11 15:09:58 +00001049 /*
1050 * This one was removed, since top level element declarations have
1051 * the target namespace specified in targetNamespace of the <schema>
1052 * information element, even if elementFormDefault is "unqualified".
1053 */
1054
1055 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001056 if (xmlStrEqual(namespace, schema->targetNamespace))
1057 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1058 else
1059 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001060 if ((ret != NULL) &&
1061 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001062 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001063 }
William M. Bracke7091952004-05-11 15:09:58 +00001064 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001065 } else {
1066 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001067 if ((ret != NULL) &&
1068 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001069 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001070 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001071 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00001072 if (level > 0)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001073 import = xmlHashLookup(schema->schemasImports, namespace);
1074 if (import != NULL)
Daniel Veillardf2a12832003-11-24 13:04:35 +00001075 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001076#ifdef DEBUG
1077 if (ret == NULL) {
1078 if (namespace == NULL)
1079 fprintf(stderr, "Unable to lookup type %s", name);
1080 else
1081 fprintf(stderr, "Unable to lookup type %s:%s", name,
1082 namespace);
1083 }
1084#endif
1085 return (ret);
1086}
1087
1088/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001089 * xmlSchemaGetType:
1090 * @schema: the schemas context
1091 * @name: the type name
1092 * @ns: the type namespace
1093 *
1094 * Lookup a type in the schemas or the predefined types
1095 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001096 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001097 */
1098static xmlSchemaTypePtr
1099xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001100 const xmlChar * namespace)
1101{
Daniel Veillard4255d502002-04-16 15:50:10 +00001102 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001103 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001104
1105 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001106 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001107 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001108 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
1109 if (ret != NULL)
1110 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001111 }
1112 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001113 if (ret != NULL)
1114 return (ret);
1115 import = xmlHashLookup(schema->schemasImports, namespace);
1116 if (import != NULL)
1117 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001118#ifdef DEBUG
1119 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001120 if (namespace == NULL)
1121 fprintf(stderr, "Unable to lookup type %s", name);
1122 else
1123 fprintf(stderr, "Unable to lookup type %s:%s", name,
1124 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001125 }
1126#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001127 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001128}
1129
1130/************************************************************************
1131 * *
1132 * Parsing functions *
1133 * *
1134 ************************************************************************/
1135
1136#define IS_BLANK_NODE(n) \
1137 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1138
1139/**
1140 * xmlSchemaIsBlank:
1141 * @str: a string
1142 *
1143 * Check if a string is ignorable
1144 *
1145 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1146 */
1147static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001148xmlSchemaIsBlank(xmlChar * str)
1149{
Daniel Veillard4255d502002-04-16 15:50:10 +00001150 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001151 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001152 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001153 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001154 return (0);
1155 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001156 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001157 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001158}
1159
1160/**
1161 * xmlSchemaAddNotation:
1162 * @ctxt: a schema validation context
1163 * @schema: the schema being built
1164 * @name: the item name
1165 *
1166 * Add an XML schema Attrribute declaration
1167 * *WARNING* this interface is highly subject to change
1168 *
1169 * Returns the new struture or NULL in case of error
1170 */
1171static xmlSchemaNotationPtr
1172xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001173 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001174{
1175 xmlSchemaNotationPtr ret = NULL;
1176 int val;
1177
1178 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1179 return (NULL);
1180
1181 if (schema->notaDecl == NULL)
1182 schema->notaDecl = xmlHashCreate(10);
1183 if (schema->notaDecl == NULL)
1184 return (NULL);
1185
1186 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1187 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001188 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001189 return (NULL);
1190 }
1191 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001192 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001193 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1194 ret);
1195 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001196 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1197 XML_SCHEMAP_REDEFINED_NOTATION,
1198 "Notation %s already defined\n",
1199 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001200 xmlFree(ret);
1201 return (NULL);
1202 }
1203 return (ret);
1204}
1205
1206
1207/**
1208 * xmlSchemaAddAttribute:
1209 * @ctxt: a schema validation context
1210 * @schema: the schema being built
1211 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001212 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001213 *
1214 * Add an XML schema Attrribute declaration
1215 * *WARNING* this interface is highly subject to change
1216 *
1217 * Returns the new struture or NULL in case of error
1218 */
1219static xmlSchemaAttributePtr
1220xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001221 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001222{
1223 xmlSchemaAttributePtr ret = NULL;
1224 int val;
1225
1226 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1227 return (NULL);
1228
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001229#ifdef DEBUG
1230 fprintf(stderr, "Adding attribute %s\n", name);
1231 if (namespace != NULL)
1232 fprintf(stderr, " target namespace %s\n", namespace);
1233#endif
1234
Daniel Veillard4255d502002-04-16 15:50:10 +00001235 if (schema->attrDecl == NULL)
1236 schema->attrDecl = xmlHashCreate(10);
1237 if (schema->attrDecl == NULL)
1238 return (NULL);
1239
1240 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1241 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001242 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001243 return (NULL);
1244 }
1245 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001246 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1247 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001248 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001249 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001250 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001251 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1252 XML_SCHEMAP_REDEFINED_ATTR,
1253 "Attribute %s already defined\n",
1254 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001255 xmlFree(ret);
1256 return (NULL);
1257 }
1258 return (ret);
1259}
1260
1261/**
1262 * xmlSchemaAddAttributeGroup:
1263 * @ctxt: a schema validation context
1264 * @schema: the schema being built
1265 * @name: the item name
1266 *
1267 * Add an XML schema Attrribute Group declaration
1268 *
1269 * Returns the new struture or NULL in case of error
1270 */
1271static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001272xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1273 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001274{
1275 xmlSchemaAttributeGroupPtr ret = NULL;
1276 int val;
1277
1278 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1279 return (NULL);
1280
1281 if (schema->attrgrpDecl == NULL)
1282 schema->attrgrpDecl = xmlHashCreate(10);
1283 if (schema->attrgrpDecl == NULL)
1284 return (NULL);
1285
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001286 ret =
1287 (xmlSchemaAttributeGroupPtr)
1288 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001289 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001290 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001291 return (NULL);
1292 }
1293 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001294 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001295 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001296 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001297 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001298 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1299 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1300 "Attribute group %s already defined\n",
1301 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001302 xmlFree(ret);
1303 return (NULL);
1304 }
1305 return (ret);
1306}
1307
1308/**
1309 * xmlSchemaAddElement:
1310 * @ctxt: a schema validation context
1311 * @schema: the schema being built
1312 * @name: the type name
1313 * @namespace: the type namespace
1314 *
1315 * Add an XML schema Element declaration
1316 * *WARNING* this interface is highly subject to change
1317 *
1318 * Returns the new struture or NULL in case of error
1319 */
1320static xmlSchemaElementPtr
1321xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1322 const xmlChar * name, const xmlChar * namespace)
1323{
1324 xmlSchemaElementPtr ret = NULL;
1325 int val;
1326
1327 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1328 return (NULL);
1329
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001330#ifdef DEBUG
1331 fprintf(stderr, "Adding element %s\n", name);
1332 if (namespace != NULL)
1333 fprintf(stderr, " target namespace %s\n", namespace);
1334#endif
1335
Daniel Veillard4255d502002-04-16 15:50:10 +00001336 if (schema->elemDecl == NULL)
1337 schema->elemDecl = xmlHashCreate(10);
1338 if (schema->elemDecl == NULL)
1339 return (NULL);
1340
1341 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1342 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001343 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001344 return (NULL);
1345 }
1346 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001347 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1348 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001349 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001350 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001351 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001352 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001353
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001354 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001355 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1356 namespace, ret);
1357 if (val != 0) {
1358 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1359 XML_SCHEMAP_REDEFINED_ELEMENT,
1360 "Element %s already defined\n",
1361 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001362 xmlFree(ret);
1363 return (NULL);
1364 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001365 }
1366 return (ret);
1367}
1368
1369/**
1370 * xmlSchemaAddType:
1371 * @ctxt: a schema validation context
1372 * @schema: the schema being built
1373 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001374 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001375 *
1376 * Add an XML schema Simple Type definition
1377 * *WARNING* this interface is highly subject to change
1378 *
1379 * Returns the new struture or NULL in case of error
1380 */
1381static xmlSchemaTypePtr
1382xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001383 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001384{
1385 xmlSchemaTypePtr ret = NULL;
1386 int val;
1387
1388 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1389 return (NULL);
1390
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001391#ifdef DEBUG
1392 fprintf(stderr, "Adding type %s\n", name);
1393 if (namespace != NULL)
1394 fprintf(stderr, " target namespace %s\n", namespace);
1395#endif
1396
Daniel Veillard4255d502002-04-16 15:50:10 +00001397 if (schema->typeDecl == NULL)
1398 schema->typeDecl = xmlHashCreate(10);
1399 if (schema->typeDecl == NULL)
1400 return (NULL);
1401
1402 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1403 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001404 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001405 return (NULL);
1406 }
1407 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001408 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001409 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001410 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001411 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001412 if (ctxt->includes == 0) {
1413 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1414 XML_SCHEMAP_REDEFINED_TYPE,
1415 "Type %s already defined\n",
1416 name, NULL);
1417 xmlFree(ret);
1418 return (NULL);
1419 } else {
1420 xmlSchemaTypePtr prev;
1421
1422 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1423 if (prev == NULL) {
1424 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1425 XML_ERR_INTERNAL_ERROR,
1426 "Internal error on type %s definition\n",
1427 name, NULL);
1428 xmlFree(ret);
1429 return (NULL);
1430 }
1431 ret->redef = prev->redef;
1432 prev->redef = ret;
1433 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001434 }
1435 ret->minOccurs = 1;
1436 ret->maxOccurs = 1;
1437
1438 return (ret);
1439}
1440
1441/**
1442 * xmlSchemaAddGroup:
1443 * @ctxt: a schema validation context
1444 * @schema: the schema being built
1445 * @name: the group name
1446 *
1447 * Add an XML schema Group definition
1448 *
1449 * Returns the new struture or NULL in case of error
1450 */
1451static xmlSchemaTypePtr
1452xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001453 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001454{
1455 xmlSchemaTypePtr ret = NULL;
1456 int val;
1457
1458 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1459 return (NULL);
1460
1461 if (schema->groupDecl == NULL)
1462 schema->groupDecl = xmlHashCreate(10);
1463 if (schema->groupDecl == NULL)
1464 return (NULL);
1465
1466 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1467 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001468 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001469 return (NULL);
1470 }
1471 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001472 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001473 val =
1474 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1475 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001476 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001477 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1478 XML_SCHEMAP_REDEFINED_GROUP,
1479 "Group %s already defined\n",
1480 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001481 xmlFree(ret);
1482 return (NULL);
1483 }
1484 ret->minOccurs = 1;
1485 ret->maxOccurs = 1;
1486
1487 return (ret);
1488}
1489
1490/************************************************************************
1491 * *
1492 * Utilities for parsing *
1493 * *
1494 ************************************************************************/
1495
1496/**
1497 * xmlGetQNameProp:
1498 * @ctxt: a schema validation context
1499 * @node: a subtree containing XML Schema informations
1500 * @name: the attribute name
1501 * @namespace: the result namespace if any
1502 *
1503 * Extract a QName Attribute value
1504 *
1505 * Returns the NCName or NULL if not found, and also update @namespace
1506 * with the namespace URI
1507 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001508static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001509xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001510 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001511{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001512 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001513 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001514 const xmlChar *ret, *prefix;
1515 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001516
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001517 *namespace = NULL;
1518 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001519 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001520 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001521
Daniel Veillardba0153a2004-04-01 10:42:31 +00001522 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00001523 ns = xmlSearchNs(node->doc, node, 0);
1524 if (ns) {
1525 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1526 return (val);
1527 }
1528 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001529 ret = xmlSplitQName3(val, &len);
1530 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001531 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001532 }
1533 ret = xmlDictLookup(ctxt->dict, ret, -1);
1534 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001535
1536 ns = xmlSearchNs(node->doc, node, prefix);
1537 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001538 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1539 "Attribute %s: the QName prefix %s is undefined\n",
1540 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001541 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001542 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001543 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001544 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001545}
1546
1547/**
1548 * xmlGetMaxOccurs:
1549 * @ctxt: a schema validation context
1550 * @node: a subtree containing XML Schema informations
1551 *
1552 * Get the maxOccurs property
1553 *
1554 * Returns the default if not found, or the value
1555 */
1556static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001557xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1558{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001559 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001560 int ret = 0;
1561
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001562 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001563 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001564 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001565
1566 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001567 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001568 }
1569
1570 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001571 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001572 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001573 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001574 ret = ret * 10 + (*cur - '0');
1575 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001576 }
William M. Brack76e95df2003-10-18 16:20:14 +00001577 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001578 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001579 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001580 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1581 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001582 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001583 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001584 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001585}
1586
1587/**
1588 * xmlGetMinOccurs:
1589 * @ctxt: a schema validation context
1590 * @node: a subtree containing XML Schema informations
1591 *
1592 * Get the minOccurs property
1593 *
1594 * Returns the default if not found, or the value
1595 */
1596static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001597xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1598{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001599 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001600 int ret = 0;
1601
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001602 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001603 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001604 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001605
1606 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001607 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001608 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001609 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001610 ret = ret * 10 + (*cur - '0');
1611 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001612 }
William M. Brack76e95df2003-10-18 16:20:14 +00001613 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001614 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001615 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001616 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1617 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001618 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001619 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001620 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001621}
1622
1623/**
1624 * xmlGetBooleanProp:
1625 * @ctxt: a schema validation context
1626 * @node: a subtree containing XML Schema informations
1627 * @name: the attribute name
1628 * @def: the default value
1629 *
1630 * Get is a bolean property is set
1631 *
1632 * Returns the default if not found, 0 if found to be false,
1633 * 1 if found to be true
1634 */
1635static int
1636xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001637 const char *name, int def)
1638{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001639 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001640
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001641 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001642 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001643 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001644
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001645 if (xmlStrEqual(val, BAD_CAST "true"))
1646 def = 1;
1647 else if (xmlStrEqual(val, BAD_CAST "false"))
1648 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001649 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001650 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1651 "Attribute %s: the value %s is not boolean\n",
1652 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001653 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001654 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001655}
1656
1657/************************************************************************
1658 * *
1659 * Shema extraction from an Infoset *
1660 * *
1661 ************************************************************************/
1662static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1663 ctxt, xmlSchemaPtr schema,
1664 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001665static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1666 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001667 xmlSchemaPtr schema,
1668 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001669static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1670 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001671 xmlSchemaPtr schema,
1672 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001673 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001674static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1675 xmlSchemaPtr schema,
1676 xmlNodePtr node);
1677static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1678 xmlSchemaPtr schema,
1679 xmlNodePtr node);
1680static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1681 ctxt,
1682 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00001683 xmlNodePtr node,
1684 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00001685static xmlSchemaAttributeGroupPtr
1686xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1687 xmlSchemaPtr schema, xmlNodePtr node);
1688static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1689 xmlSchemaPtr schema,
1690 xmlNodePtr node);
1691static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1692 xmlSchemaPtr schema,
1693 xmlNodePtr node);
1694static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001695xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1696 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001697
1698/**
1699 * xmlSchemaParseAttrDecls:
1700 * @ctxt: a schema validation context
1701 * @schema: the schema being built
1702 * @node: a subtree containing XML Schema informations
1703 * @type: the hosting type
1704 *
1705 * parse a XML schema attrDecls declaration corresponding to
1706 * <!ENTITY % attrDecls
1707 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1708 */
1709static xmlNodePtr
1710xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1711 xmlNodePtr child, xmlSchemaTypePtr type)
1712{
1713 xmlSchemaAttributePtr lastattr, attr;
1714
1715 lastattr = NULL;
1716 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001717 (IS_SCHEMA(child, "attributeGroup"))) {
1718 attr = NULL;
1719 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00001720 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001721 } else if (IS_SCHEMA(child, "attributeGroup")) {
1722 attr = (xmlSchemaAttributePtr)
1723 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1724 }
1725 if (attr != NULL) {
1726 if (lastattr == NULL) {
1727 type->attributes = attr;
1728 lastattr = attr;
1729 } else {
1730 lastattr->next = attr;
1731 lastattr = attr;
1732 }
1733 }
1734 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001735 }
1736 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001737 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1738 if (attr != NULL) {
1739 if (lastattr == NULL) {
1740 type->attributes = attr;
1741 lastattr = attr;
1742 } else {
1743 lastattr->next = attr;
1744 lastattr = attr;
1745 }
1746 }
1747 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001748 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001749 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001750}
1751
1752/**
1753 * xmlSchemaParseAnnotation:
1754 * @ctxt: a schema validation context
1755 * @schema: the schema being built
1756 * @node: a subtree containing XML Schema informations
1757 *
1758 * parse a XML schema Attrribute declaration
1759 * *WARNING* this interface is highly subject to change
1760 *
William M. Bracke7091952004-05-11 15:09:58 +00001761 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00001762 * 1 in case of success.
1763 */
1764static xmlSchemaAnnotPtr
1765xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1766 xmlNodePtr node)
1767{
1768 xmlSchemaAnnotPtr ret;
1769
1770 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1771 return (NULL);
1772 ret = xmlSchemaNewAnnot(ctxt, node);
1773
1774 return (ret);
1775}
1776
1777/**
1778 * xmlSchemaParseFacet:
1779 * @ctxt: a schema validation context
1780 * @schema: the schema being built
1781 * @node: a subtree containing XML Schema informations
1782 *
1783 * parse a XML schema Facet declaration
1784 * *WARNING* this interface is highly subject to change
1785 *
1786 * Returns the new type structure or NULL in case of error
1787 */
1788static xmlSchemaFacetPtr
1789xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001790 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001791{
1792 xmlSchemaFacetPtr facet;
1793 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001794 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00001795
1796 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1797 return (NULL);
1798
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001799 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001800 if (facet == NULL) {
1801 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1802 return (NULL);
1803 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001804 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001805 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00001806 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001807 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1808 "Facet %s has no value\n", node->name, NULL);
1809 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001810 return (NULL);
1811 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001812 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001813 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001814 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001815 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001816 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001817 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001818 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001819 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001820 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001821 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001822 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001823 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001824 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001825 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001826 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001827 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001828 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001829 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001830 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001831 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001832 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001833 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1834 } else if (IS_SCHEMA(node, "minLength")) {
1835 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1836 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001837 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1838 "Unknown facet type %s\n", node->name, NULL);
1839 xmlSchemaFreeFacet(facet);
1840 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001841 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001842 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00001843 facet->value = value;
1844 child = node->children;
1845
1846 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001847 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1848 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001849 }
1850 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001851 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1852 "Facet %s has unexpected child content\n",
1853 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001854 }
1855 return (facet);
1856}
1857
1858/**
1859 * xmlSchemaParseAny:
1860 * @ctxt: a schema validation context
1861 * @schema: the schema being built
1862 * @node: a subtree containing XML Schema informations
1863 *
1864 * parse a XML schema Any declaration
1865 * *WARNING* this interface is highly subject to change
1866 *
1867 * Returns the new type structure or NULL in case of error
1868 */
1869static xmlSchemaTypePtr
1870xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1871 xmlNodePtr node)
1872{
1873 xmlSchemaTypePtr type;
1874 xmlNodePtr child = NULL;
1875 xmlChar name[30];
1876
1877 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1878 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001879 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001880 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001881 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001882 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001883 type->node = node;
1884 type->type = XML_SCHEMA_TYPE_ANY;
1885 child = node->children;
1886 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1887 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1888
1889 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001890 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1891 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001892 }
1893 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001894 xmlSchemaPErr2(ctxt, node, child,
1895 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1896 "Sequence %s has unexpected content\n", type->name,
1897 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001898 }
1899
1900 return (type);
1901}
1902
1903/**
1904 * xmlSchemaParseNotation:
1905 * @ctxt: a schema validation context
1906 * @schema: the schema being built
1907 * @node: a subtree containing XML Schema informations
1908 *
1909 * parse a XML schema Notation declaration
1910 *
1911 * Returns the new structure or NULL in case of error
1912 */
1913static xmlSchemaNotationPtr
1914xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001915 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001916{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001917 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00001918 xmlSchemaNotationPtr ret;
1919 xmlNodePtr child = NULL;
1920
1921 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1922 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001923 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001924 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001925 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1926 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001927 return (NULL);
1928 }
1929 ret = xmlSchemaAddNotation(ctxt, schema, name);
1930 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001931 return (NULL);
1932 }
1933 child = node->children;
1934 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001935 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1936 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001937 }
1938 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001939 xmlSchemaPErr2(ctxt, node, child,
1940 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1941 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001942 }
1943
1944 return (ret);
1945}
1946
1947/**
1948 * xmlSchemaParseAnyAttribute:
1949 * @ctxt: a schema validation context
1950 * @schema: the schema being built
1951 * @node: a subtree containing XML Schema informations
1952 *
1953 * parse a XML schema AnyAttrribute declaration
1954 * *WARNING* this interface is highly subject to change
1955 *
1956 * Returns an attribute def structure or NULL
1957 */
1958static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001959xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1960 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001961{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001962 const xmlChar *processContents;
Daniel Veillard4255d502002-04-16 15:50:10 +00001963 xmlSchemaAttributePtr ret;
1964 xmlNodePtr child = NULL;
1965 char name[100];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001966
Daniel Veillard4255d502002-04-16 15:50:10 +00001967
1968 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1969 return (NULL);
1970
1971 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
William M. Bracke7091952004-05-11 15:09:58 +00001972
1973 /* local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns); */
1974
1975 /*
1976 * TODO: namespace = ((##any | ##other) | List of (anyURI |
1977 * (##targetNamespace | * ##local)) ) : ##any
1978 */
1979 ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001980 if (ret == NULL) {
1981 return (NULL);
1982 }
William M. Bracke7091952004-05-11 15:09:58 +00001983 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001984 ret->id = xmlSchemaGetProp(ctxt, node, "id");
1985 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001986 if ((processContents == NULL)
1987 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1988 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1989 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1990 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1991 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1992 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001993 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001994 xmlSchemaPErr2(ctxt, node, child,
1995 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
William M. Bracke7091952004-05-11 15:09:58 +00001996 "anyAttribute has unexpected content "
1997 "for processContents: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001998 processContents, NULL);
1999 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00002000 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002001
2002 child = node->children;
2003 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002004 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2005 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002006 }
2007 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002008 xmlSchemaPErr2(ctxt, node, child,
2009 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
2010 "anyAttribute %s has unexpected content\n",
2011 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002012 }
2013
2014 return (ret);
2015}
2016
2017
2018/**
2019 * xmlSchemaParseAttribute:
2020 * @ctxt: a schema validation context
2021 * @schema: the schema being built
2022 * @node: a subtree containing XML Schema informations
2023 *
2024 * parse a XML schema Attrribute declaration
2025 * *WARNING* this interface is highly subject to change
2026 *
William M. Bracke7091952004-05-11 15:09:58 +00002027 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002028 */
2029static xmlSchemaAttributePtr
2030xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002031 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002032{
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002033 const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal;
Daniel Veillard4255d502002-04-16 15:50:10 +00002034 xmlSchemaAttributePtr ret;
2035 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002036 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002037 int hasRefType = 0;
William M. Bracke7091952004-05-11 15:09:58 +00002038
2039 /*
2040 * Note that the w3c spec assumes the schema to be validated with schema
2041 * for schemas beforehand.
2042 *
2043 * 3.2.3 Constraints on XML Representations of Attribute Declarations
2044 *
2045 * TODO: Complete implementation of:
2046 * 3.2.6 Schema Component Constraint: Attribute Declaration Properties
2047 * Correct
2048 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002049
2050 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2051 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002052
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002053 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002054 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002055 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002056 /* 3.2.3 : 3.1
2057 * One of ref or name must be present, but not both
2058 */
2059 if (ref == NULL) {
2060 xmlSchemaPErr(ctxt, node,
2061 XML_SCHEMAP_ATTR_NONAME_NOREF,
2062 "Attribute declaration has no \"name\" or \"ref\"\n",
2063 NULL, NULL);
2064 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002065 }
William M. Bracke7091952004-05-11 15:09:58 +00002066 hasRefType = 1;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002067 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2068 name = (const xmlChar *) buf;
2069 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002070 if (!topLevel) {
2071 /* 3.2.3 : 3.2
2072 * If ref is present, then all of <simpleType>,
2073 * form and type must be absent.
2074 */
2075 if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2076 xmlSchemaPErr(ctxt, node,
2077 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2078 "Attribute declaration %s has \"ref\", thus "
2079 "\"form\" must be absent\n", name, NULL);
2080 }
2081 if (xmlSchemaGetProp(ctxt, node, "type") != NULL) {
2082 xmlSchemaPErr(ctxt, node,
2083 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2084 "Attribute declaration %s has \"ref\", thus "
2085 "\"type\" must be absent\n", name, NULL);
2086 }
2087 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002088 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002089 const xmlChar *ns = NULL;
2090 /* 3.2.3 : 3.1
2091 * One of ref or name must be present, but not both
2092 */
2093 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2094 xmlSchemaPErr(ctxt, node,
2095 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2096 "Attribute declaration has both, \"name\" and "
2097 "\"ref\"\n", NULL, NULL);
2098 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002099
William M. Bracke7091952004-05-11 15:09:58 +00002100 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2101 /* Evaluate the target namespace */
2102 if (schema->targetNamespace != NULL) {
2103 if (topLevel) {
2104 ns = schema->targetNamespace;
2105 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2106 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2107 BAD_CAST "qualified")) {
2108 ns = schema->targetNamespace;
2109 }
2110 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2111 ns = schema->targetNamespace;
2112 }
2113 }
2114 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns);
2115
2116 /* 3.2.6 Schema Component Constraint: xmlns Not Allowed */
2117 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2118 xmlSchemaPErr(ctxt, node,
2119 XML_SCHEMAP_INVALID_ATTR_NAME,
2120 "The name of an attribute declaration must not match "
2121 "\"xmlns\".\n", NULL, NULL);
2122 }
2123
2124 /* 3.2.6 Schema Component Constraint: xsi: Not Allowed */
2125 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
2126 xmlSchemaPErr(ctxt, node,
2127 XML_SCHEMAP_INVALID_ATTR_NAME,
2128 "The target namespace of an attribute declaration, "
2129 "must not match \"http://www.w3.org/2001/"
2130 "XMLSchema-instance\"", NULL, NULL);
2131 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002132 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002133 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002134 return (NULL);
2135 }
William M. Bracke7091952004-05-11 15:09:58 +00002136 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
2137
2138 /* Handle the "use" attribute. */
2139 attrVal = xmlSchemaGetProp(ctxt, node, "use");
2140 if (attrVal != NULL) {
2141 if (xmlStrEqual(attrVal, BAD_CAST "optional"))
2142 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2143 else if (xmlStrEqual(attrVal, BAD_CAST "prohibited"))
2144 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
2145 else if (xmlStrEqual(attrVal, BAD_CAST "required"))
2146 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
2147 else
2148 xmlSchemaPErr(ctxt, node,
2149 XML_SCHEMAP_INVALID_ATTR_USE,
2150 "Attribute declaration %s has an invalid "
2151 "value for \"use\"\n", name, NULL);
2152 } else
2153 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002154
William M. Bracke7091952004-05-11 15:09:58 +00002155
2156 if (xmlSchemaGetProp(ctxt, node, "default") != NULL) {
2157 /* 3.2.3 : 1
2158 * default and fixed must not both be present.
2159 */
2160 if (xmlSchemaGetProp(ctxt, node, "fixed") != NULL) {
2161 xmlSchemaPErr(ctxt, node,
2162 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2163 "Attribute declaration has both, \"default\" "
2164 "and \"fixed\"\n", NULL, NULL);
2165 }
2166 /* 3.2.3 : 2
2167 * If default and use are both present, use must have
2168 * the actual value optional.
2169 */
2170 if (ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) {
2171 xmlSchemaPErr(ctxt, node,
2172 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2173 "Attribute declaration has \"default\" but "
2174 "\"use\" is not \"optional\"\n", NULL, NULL);
2175 }
2176 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002177
Daniel Veillard4255d502002-04-16 15:50:10 +00002178 ret->ref = ref;
2179 ret->refNs = refNs;
William M. Bracke7091952004-05-11 15:09:58 +00002180 /*
2181 * The setting of XML_SCHEMAS_ATTR_NSDEFAULT is not needed anymore,
2182 * since the target namespace was already evaluated and took
2183 * attributeFormDefault into account.
2184 */
2185 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002186 if ((ret->targetNamespace != NULL) &&
2187 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2188 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2189 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
William M. Bracke7091952004-05-11 15:09:58 +00002190 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002191 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
William M. Bracke7091952004-05-11 15:09:58 +00002192 if (ret->typeName != NULL)
2193 hasRefType = 1;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002194 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002195 child = node->children;
2196 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002197 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2198 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002199 }
2200 if (IS_SCHEMA(child, "simpleType")) {
William M. Bracke7091952004-05-11 15:09:58 +00002201 if (hasRefType) {
2202 /* 3.2.3 : 4
2203 * type and <simpleType> must not both be present.
2204 *
2205 * TODO: XML_SCHEMAP_INVALID_ATTR_COMBINATION seems not to be
2206 * a proper error type here.
2207 */
2208 xmlSchemaPErr2(ctxt, node, child,
2209 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2210 "Attribute declaration %s has both (\"ref\" or "
2211 "\"type\") and <simpleType>\n", name, NULL);
2212 } else
2213 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002214 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002215 }
2216 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002217 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2218 "attribute %s has unexpected content\n", name,
2219 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002220 }
2221
2222 return (ret);
2223}
2224
2225/**
2226 * xmlSchemaParseAttributeGroup:
2227 * @ctxt: a schema validation context
2228 * @schema: the schema being built
2229 * @node: a subtree containing XML Schema informations
2230 *
2231 * parse a XML schema Attribute Group declaration
2232 * *WARNING* this interface is highly subject to change
2233 *
2234 * Returns the attribute group or NULL in case of error.
2235 */
2236static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002237xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
2238 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002239{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002240 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002241 xmlSchemaAttributeGroupPtr ret;
2242 xmlSchemaAttributePtr last = NULL, attr;
2243 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002244 const xmlChar *oldcontainer;
2245 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002246
2247 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2248 return (NULL);
2249 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002250 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002251 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002252
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002253 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2254 if (ref == NULL) {
2255 xmlSchemaPErr2(ctxt, node, child,
2256 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2257 "AttributeGroup has no name nor ref\n", NULL,
2258 NULL);
2259 return (NULL);
2260 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002261 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2262 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002263 if (name == NULL) {
2264 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2265 return (NULL);
2266 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002267 }
2268 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2269 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002270 return (NULL);
2271 }
2272 ret->ref = ref;
2273 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002274 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002275 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002276 child = node->children;
2277 ctxt->container = name;
2278 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002279 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2280 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002281 }
2282 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002283 (IS_SCHEMA(child, "attributeGroup"))) {
2284 attr = NULL;
2285 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00002286 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002287 } else if (IS_SCHEMA(child, "attributeGroup")) {
2288 attr = (xmlSchemaAttributePtr)
2289 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2290 }
2291 if (attr != NULL) {
2292 if (last == NULL) {
2293 ret->attributes = attr;
2294 last = attr;
2295 } else {
2296 last->next = attr;
2297 last = attr;
2298 }
2299 }
2300 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002301 }
2302 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002303 TODO
2304 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002305 }
2306 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002307 xmlSchemaPErr2(ctxt, node, child,
2308 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2309 "attribute group %s has unexpected content\n", name,
2310 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002311 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002312 ctxt->container = oldcontainer;
2313 return (ret);
2314}
2315
2316/**
2317 * xmlSchemaParseElement:
2318 * @ctxt: a schema validation context
2319 * @schema: the schema being built
2320 * @node: a subtree containing XML Schema informations
2321 *
2322 * parse a XML schema Element declaration
2323 * *WARNING* this interface is highly subject to change
2324 *
William M. Bracke7091952004-05-11 15:09:58 +00002325 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002326 */
2327static xmlSchemaElementPtr
2328xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2329 xmlNodePtr node, int toplevel)
2330{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002331 const xmlChar *name, *fixed;
2332 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002333 xmlSchemaElementPtr ret;
2334 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002335 const xmlChar *oldcontainer;
2336 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002337 xmlAttrPtr attr;
2338
2339 /* 3.3.3 Constraints on XML Representations of Element Declarations */
2340 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002341
2342 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2343 return (NULL);
2344 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002345 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002346 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002347
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002348 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002349 /* 3.3.3 : 2.1
2350 * One of ref or name must be present, but not both
2351 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002352 if (ref == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00002353 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002354 XML_SCHEMAP_ELEM_NONAME_NOREF,
2355 "Element has no name nor ref\n", NULL, NULL);
2356 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002357 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002358 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2359 name = (const xmlChar *) buf;
2360 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2361 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002362 const xmlChar *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002363
William M. Bracke7091952004-05-11 15:09:58 +00002364 /* Evaluate the target namespace */
2365 if (schema->targetNamespace != NULL) {
2366 if (toplevel) {
2367 ns = schema->targetNamespace;
2368 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2369 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2370 BAD_CAST "qualified")) {
2371 ns = schema->targetNamespace;
2372 }
2373 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2374 ns = schema->targetNamespace;
2375 }
2376 }
2377 /*local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2378 ret = xmlSchemaAddElement(ctxt, schema, name, ns);
2379 /* 3.3.3 : 2.1
2380 * One of ref or name must be present, but not both
2381 */
2382 if ((!toplevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2383 xmlSchemaPErr(ctxt, node,
2384 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2385 "Element declaration has both, \"name\" and "
2386 "\"ref\"\n", NULL, NULL);
2387 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002388 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002389 if (ret != NULL)
2390 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002391 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002392 return (NULL);
2393 }
2394 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2395 ret->ref = ref;
2396 ret->refNs = refNs;
2397 if (ref != NULL)
2398 ret->flags |= XML_SCHEMAS_ELEM_REF;
William M. Bracke7091952004-05-11 15:09:58 +00002399
2400 /* 3.3.3 : 2.2 */
2401 if ((!toplevel) && (ref != NULL)) {
2402 attr = node->properties;
2403 while (attr != NULL) {
2404 if ((attr->ns == NULL) &&
2405 (!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
2406 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
2407 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
2408 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
2409
2410 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2411 "Element declaration %s: only minOccurs, maxOccurs "
2412 "and id are allowed in addition to ref\n",
2413 ret->name, NULL);
2414 }
2415 attr = attr->next;
2416 }
2417 }
2418
Daniel Veillard4255d502002-04-16 15:50:10 +00002419 if (toplevel)
2420 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2421 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2422 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2423 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2424 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2425 ctxt->container = name;
2426
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002427 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002428 ret->namedType =
William M. Bracke7091952004-05-11 15:09:58 +00002429 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002430 ret->substGroup =
2431 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2432 &(ret->substGroupNs));
William M. Bracke7091952004-05-11 15:09:58 +00002433 if ((ret->substGroup != NULL) && (!toplevel)) {
2434 /* 3.3.6 : 3 */
2435 /*
2436 * TODO: This seems to be redundant, since the schema for schemas
2437 * already prohibits the use of the "substitutionGroup" attribute
2438 * in local element declarations.
2439 */
2440 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2441 "Element declaration %s: substitutionGroup is allowed "
2442 "on top-level declarations only\n", ret->name, NULL);
2443
2444 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002445 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002446 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2447 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002448
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002449 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002450 if ((ret->value != NULL) && (fixed != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00002451 /* 3.3.3 : 1
2452 * default and fixed must not both be present.
2453 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002454 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2455 "Element %s has both default and fixed\n",
2456 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002457 } else if (fixed != NULL) {
2458 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002459 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002460 }
2461
2462 child = node->children;
2463 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002464 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2465 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002466 }
William M. Bracke7091952004-05-11 15:09:58 +00002467 if (ref != NULL) {
2468 /* 3.3.3 (2.2) */
2469 while (child != NULL) {
2470 if ((IS_SCHEMA(child, "complexType")) ||
2471 (IS_SCHEMA(child, "simpleType")) ||
2472 (IS_SCHEMA(child, "unique")) ||
2473 (IS_SCHEMA(child, "key")) ||
2474 (IS_SCHEMA(child, "keyref"))) {
2475
2476 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_REF_AND_CONTENT,
2477 "Element declaration %s: only annotation is "
2478 "allowed as content in addition to ref\n",
2479 ret->name, NULL);
2480 } else {
2481 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2482 "element %s has unexpected content\n", name, NULL);
2483 }
2484 child = child->next;
2485 }
2486 } else {
2487 if (IS_SCHEMA(child, "complexType")) {
2488 /* 3.3.3 : 3
2489 * type and either <simpleType> or <complexType> are mutually
2490 * exclusive
2491 */
2492 if (ret->namedType != NULL) {
2493 xmlSchemaPErr2(ctxt, node, child,
2494 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2495 "Element declaration %s has both \"type\" "
2496 "and a local complex type\n",
2497 ret->name, NULL);
2498 } else
2499 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
2500 child = child->next;
2501 } else if (IS_SCHEMA(child, "simpleType")) {
2502 /* 3.3.3 : 3
2503 * type and either <simpleType> or <complexType> are
2504 * mutually exclusive
2505 */
2506 if (ret->namedType != NULL) {
2507 xmlSchemaPErr2(ctxt, node, child,
2508 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2509 "Element declaration %s has both \"type\" "
2510 "and a local simple type\n",
2511 ret->name, NULL);
2512 } else
2513 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2514 child = child->next;
2515 }
2516
2517 while ((IS_SCHEMA(child, "unique")) ||
2518 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2519 TODO child = child->next;
2520 }
2521 if (child != NULL) {
2522 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2523 "element %s has unexpected content\n", name, NULL);
2524 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002525 }
2526
2527 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002528 return (ret);
2529}
2530
2531/**
2532 * xmlSchemaParseUnion:
2533 * @ctxt: a schema validation context
2534 * @schema: the schema being built
2535 * @node: a subtree containing XML Schema informations
2536 *
2537 * parse a XML schema Union definition
2538 * *WARNING* this interface is highly subject to change
2539 *
William M. Bracke7091952004-05-11 15:09:58 +00002540 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002541 * 1 in case of success.
2542 */
2543static xmlSchemaTypePtr
2544xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002545 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002546{
2547 xmlSchemaTypePtr type, subtype, last = NULL;
2548 xmlNodePtr child = NULL;
2549 xmlChar name[30];
2550
2551 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2552 return (NULL);
2553
2554
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002555 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002556 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002557 if (type == NULL)
2558 return (NULL);
2559 type->node = node;
Daniel Veillard377e1a92004-04-16 16:30:05 +00002560 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002561 type->id = xmlSchemaGetProp(ctxt, node, "id");
2562 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002563
2564 child = node->children;
2565 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002566 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2567 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002568 }
2569 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002570 subtype = (xmlSchemaTypePtr)
2571 xmlSchemaParseSimpleType(ctxt, schema, child);
2572 if (subtype != NULL) {
2573 if (last == NULL) {
2574 type->subtypes = subtype;
2575 last = subtype;
2576 } else {
2577 last->next = subtype;
2578 last = subtype;
2579 }
2580 last->next = NULL;
2581 }
2582 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002583 }
2584 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002585 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2586 "Union %s has unexpected content\n", type->name,
2587 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002588 }
2589 return (type);
2590}
2591
2592/**
2593 * xmlSchemaParseList:
2594 * @ctxt: a schema validation context
2595 * @schema: the schema being built
2596 * @node: a subtree containing XML Schema informations
2597 *
2598 * parse a XML schema List definition
2599 * *WARNING* this interface is highly subject to change
2600 *
William M. Bracke7091952004-05-11 15:09:58 +00002601 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002602 * 1 in case of success.
2603 */
2604static xmlSchemaTypePtr
2605xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002606 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002607{
2608 xmlSchemaTypePtr type, subtype;
2609 xmlNodePtr child = NULL;
2610 xmlChar name[30];
2611
2612 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2613 return (NULL);
2614
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002615 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002616 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002617 if (type == NULL)
2618 return (NULL);
2619 type->node = node;
2620 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002621 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002622 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2623
2624 child = node->children;
2625 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002626 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2627 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002628 }
William M. Bracke7091952004-05-11 15:09:58 +00002629
Daniel Veillard4255d502002-04-16 15:50:10 +00002630 subtype = NULL;
2631 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002632 subtype = (xmlSchemaTypePtr)
2633 xmlSchemaParseSimpleType(ctxt, schema, child);
2634 child = child->next;
2635 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002636 }
2637 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002638 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2639 "List %s has unexpected content\n", type->name,
2640 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002641 }
2642 return (type);
2643}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002644
Daniel Veillard4255d502002-04-16 15:50:10 +00002645/**
2646 * xmlSchemaParseSimpleType:
2647 * @ctxt: a schema validation context
2648 * @schema: the schema being built
2649 * @node: a subtree containing XML Schema informations
2650 *
2651 * parse a XML schema Simple Type definition
2652 * *WARNING* this interface is highly subject to change
2653 *
William M. Bracke7091952004-05-11 15:09:58 +00002654 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002655 * 1 in case of success.
2656 */
2657static xmlSchemaTypePtr
2658xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2659 xmlNodePtr node)
2660{
2661 xmlSchemaTypePtr type, subtype;
2662 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002663 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002664
2665 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2666 return (NULL);
2667
2668
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002669 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002670 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002671 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002672
William M. Bracke7091952004-05-11 15:09:58 +00002673 snprintf(buf, 99, "simpleType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002674 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002675 } else {
2676 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2677 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002678 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002679 if (type == NULL)
2680 return (NULL);
2681 type->node = node;
2682 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002683 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002684
2685 child = node->children;
2686 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002687 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2688 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002689 }
2690 subtype = NULL;
2691 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002692 subtype = (xmlSchemaTypePtr)
2693 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2694 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002695 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002696 subtype = (xmlSchemaTypePtr)
2697 xmlSchemaParseList(ctxt, schema, child);
2698 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002699 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002700 subtype = (xmlSchemaTypePtr)
2701 xmlSchemaParseUnion(ctxt, schema, child);
2702 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002703 }
2704 type->subtypes = subtype;
William M. Bracke7091952004-05-11 15:09:58 +00002705 if (subtype == NULL) {
2706 xmlSchemaPErr2(ctxt, node, child,
2707 XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD,
2708 "SimpleType %s does not define a variety\n",
2709 type->name, NULL);
2710 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002711 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002712 xmlSchemaPErr2(ctxt, node, child,
2713 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2714 "SimpleType %s has unexpected content\n",
2715 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002716 }
2717
2718 return (type);
2719}
2720
2721
2722/**
2723 * xmlSchemaParseGroup:
2724 * @ctxt: a schema validation context
2725 * @schema: the schema being built
2726 * @node: a subtree containing XML Schema informations
2727 *
2728 * parse a XML schema Group definition
2729 * *WARNING* this interface is highly subject to change
2730 *
William M. Bracke7091952004-05-11 15:09:58 +00002731 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002732 * 1 in case of success.
2733 */
2734static xmlSchemaTypePtr
2735xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002736 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002737{
2738 xmlSchemaTypePtr type, subtype;
2739 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002740 const xmlChar *name;
2741 const xmlChar *ref = NULL, *refNs = NULL;
2742 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002743
2744 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2745 return (NULL);
2746
2747
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002748 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002749 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002750
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002751 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2752 if (ref == NULL) {
2753 xmlSchemaPErr2(ctxt, node, child,
2754 XML_SCHEMAP_GROUP_NONAME_NOREF,
2755 "Group has no name nor ref\n", NULL, NULL);
2756 return (NULL);
2757 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002758 if (refNs == NULL)
2759 refNs = schema->targetNamespace;
2760 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2761 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00002762 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002763 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002764 if (type == NULL)
2765 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00002766
Daniel Veillard4255d502002-04-16 15:50:10 +00002767 type->node = node;
2768 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002769 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002770 type->ref = ref;
2771 type->refNs = refNs;
2772 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2773 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2774
2775 child = node->children;
2776 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002777 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2778 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002779 }
2780 subtype = NULL;
2781 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002782 subtype = (xmlSchemaTypePtr)
2783 xmlSchemaParseAll(ctxt, schema, child);
2784 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002785 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002786 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2787 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002788 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002789 subtype = (xmlSchemaTypePtr)
2790 xmlSchemaParseSequence(ctxt, schema, child);
2791 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002792 }
2793 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002794 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002795 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002796 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2797 "Group %s has unexpected content\n", type->name,
2798 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002799 }
2800
2801 return (type);
2802}
2803
2804/**
2805 * xmlSchemaParseAll:
2806 * @ctxt: a schema validation context
2807 * @schema: the schema being built
2808 * @node: a subtree containing XML Schema informations
2809 *
2810 * parse a XML schema All definition
2811 * *WARNING* this interface is highly subject to change
2812 *
William M. Bracke7091952004-05-11 15:09:58 +00002813 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002814 * 1 in case of success.
2815 */
2816static xmlSchemaTypePtr
2817xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002818 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002819{
2820 xmlSchemaTypePtr type, subtype, last = NULL;
2821 xmlNodePtr child = NULL;
2822 xmlChar name[30];
2823
2824 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2825 return (NULL);
2826
2827
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002828 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002829 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002830 if (type == NULL)
2831 return (NULL);
2832 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002833 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002834 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002835 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002836 if (type->minOccurs > 1)
2837 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2838 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002839 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002840 if (type->maxOccurs > 1)
2841 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2842 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002843
2844 child = node->children;
2845 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002846 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2847 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002848 }
2849 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002850 subtype = (xmlSchemaTypePtr)
2851 xmlSchemaParseElement(ctxt, schema, child, 0);
2852 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00002853 if (subtype->minOccurs > 1)
2854 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
2855 "invalid value for minOccurs (must be 0 or 1)\n",
2856 NULL, NULL);
2857 if (subtype->maxOccurs > 1)
2858 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
2859 "invalid value for maxOccurs (must be 0 or 1)\n",
2860 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002861 if (last == NULL) {
2862 type->subtypes = subtype;
2863 last = subtype;
2864 } else {
2865 last->next = subtype;
2866 last = subtype;
2867 }
2868 last->next = NULL;
2869 }
2870 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002871 }
2872 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002873 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2874 "All %s has unexpected content\n", type->name,
2875 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002876 }
2877
2878 return (type);
2879}
2880
2881/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002882 * xmlSchemaImportSchema
2883 *
2884 * @ctxt: a schema validation context
2885 * @schemaLocation: an URI defining where to find the imported schema
2886 *
2887 * import a XML schema
2888 * *WARNING* this interface is highly subject to change
2889 *
2890 * Returns -1 in case of error and 1 in case of success.
2891 */
2892static xmlSchemaImportPtr
2893xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2894 const xmlChar *schemaLocation)
2895{
2896 xmlSchemaImportPtr import;
2897 xmlSchemaParserCtxtPtr newctxt;
2898
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002899 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00002900 if (newctxt == NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002901 xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00002902 NULL);
2903 return (NULL);
2904 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002905 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
2906 /* Keep the same dictionnary for parsing, really */
2907 xmlDictReference(ctxt->dict);
2908 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002909 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002910 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
2911
Daniel Veillard1d913862003-11-21 00:28:39 +00002912 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2913 ctxt->userData);
2914
2915 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2916 if (import == NULL) {
2917 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2918 NULL);
2919 xmlSchemaFreeParserCtxt(newctxt);
2920 return (NULL);
2921 }
2922
2923 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002924 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00002925 import->schema = xmlSchemaParse(newctxt);
2926
2927 if (import->schema == NULL) {
2928 /* FIXME use another error enum here ? */
2929 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2930 "failed to import schema at location %s\n",
2931 schemaLocation, NULL);
2932
2933 xmlSchemaFreeParserCtxt(newctxt);
2934 if (import->schemaLocation != NULL)
2935 xmlFree((xmlChar *)import->schemaLocation);
2936 xmlFree(import);
2937 return NULL;
2938 }
2939
2940 xmlSchemaFreeParserCtxt(newctxt);
2941 return import;
2942}
2943
2944
2945/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002946 * xmlSchemaParseImport:
2947 * @ctxt: a schema validation context
2948 * @schema: the schema being built
2949 * @node: a subtree containing XML Schema informations
2950 *
2951 * parse a XML schema Import definition
2952 * *WARNING* this interface is highly subject to change
2953 *
William M. Bracke7091952004-05-11 15:09:58 +00002954 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard5a872412002-05-22 06:40:27 +00002955 * 1 in case of success.
2956 */
2957static int
2958xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002959 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002960{
2961 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00002962 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002963 const xmlChar *namespace;
2964 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00002965 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00002966 xmlURIPtr check;
2967
Daniel Veillard1d913862003-11-21 00:28:39 +00002968
Daniel Veillard5a872412002-05-22 06:40:27 +00002969 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2970 return (-1);
2971
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002972 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00002973 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002974 check = xmlParseURI((const char *) namespace);
2975 if (check == NULL) {
2976 xmlSchemaPErr2(ctxt, node, child,
2977 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2978 "Import namespace attribute is not an URI: %s\n",
2979 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002980 return (-1);
2981 } else {
2982 xmlFreeURI(check);
2983 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002984 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002985 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00002986 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002987 xmlChar *base = NULL;
2988 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002989 check = xmlParseURI((const char *) schemaLocation);
2990 if (check == NULL) {
2991 xmlSchemaPErr2(ctxt, node, child,
2992 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2993 "Import schemaLocation attribute is not an URI: %s\n",
2994 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002995 return (-1);
2996 } else {
2997 xmlFreeURI(check);
2998 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002999 base = xmlNodeGetBase(node->doc, node);
3000 if (base == NULL) {
3001 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3002 } else {
3003 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003004 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00003005 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003006 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003007 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3008 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00003009 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003010 }
3011 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003012 schema->schemasImports = xmlHashCreate(10);
3013 if (schema->schemasImports == NULL) {
3014 xmlSchemaPErr2(ctxt, node, child,
3015 XML_SCHEMAP_FAILED_BUILD_IMPORT,
3016 "Internal: failed to build import table\n",
3017 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003018 return (-1);
3019 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003020 }
3021 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003022 import = xmlHashLookup(schema->schemasImports,
3023 XML_SCHEMAS_DEFAULT_NAMESPACE);
3024 if (import != NULL)
3025 previous = import->schemaLocation;
3026 else
3027 previous = NULL;
3028
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003029 if (schemaLocation != NULL) {
3030 if (previous != NULL) {
3031 if (!xmlStrEqual(schemaLocation, previous)) {
3032 xmlSchemaPErr2(ctxt, node, child,
3033 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003034 "Redefining import for default namespace "
3035 "with a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003036 schemaLocation, NULL);
3037 }
3038 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003039 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3040 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003041 return (-1);
3042 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003043 xmlHashAddEntry(schema->schemasImports,
3044 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00003045 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003046 }
3047 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003048 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003049 import = xmlHashLookup(schema->schemasImports, namespace);
3050 if (import != NULL)
3051 previous = import->schemaLocation;
3052 else
3053 previous = NULL;
3054
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003055 if (schemaLocation != NULL) {
3056 if (previous != NULL) {
3057 if (!xmlStrEqual(schemaLocation, previous)) {
3058 xmlSchemaPErr2(ctxt, node, child,
3059 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003060 "Redefining import for namespace %s with "
3061 "a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003062 namespace, schemaLocation);
3063 }
3064 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003065 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3066 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003067 return (-1);
3068 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003069 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00003070 namespace, import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003071 }
3072 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003073 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003074
3075 child = node->children;
3076 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003077 /*
3078 * the annotations here are simply discarded ...
3079 */
3080 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00003081 }
3082 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003083 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
3084 "Import has unexpected content\n", NULL, NULL);
3085 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003086 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003087 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003088}
3089
3090/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003091 * xmlSchemaCleanupDoc:
3092 * @ctxt: a schema validation context
3093 * @node: the root of the document.
3094 *
3095 * removes unwanted nodes in a schemas document tree
3096 */
3097static void
3098xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
3099{
3100 xmlNodePtr delete, cur;
3101
3102 if ((ctxt == NULL) || (root == NULL)) return;
3103
3104 /*
3105 * Remove all the blank text nodes
3106 */
3107 delete = NULL;
3108 cur = root;
3109 while (cur != NULL) {
3110 if (delete != NULL) {
3111 xmlUnlinkNode(delete);
3112 xmlFreeNode(delete);
3113 delete = NULL;
3114 }
3115 if (cur->type == XML_TEXT_NODE) {
3116 if (IS_BLANK_NODE(cur)) {
3117 if (xmlNodeGetSpacePreserve(cur) != 1) {
3118 delete = cur;
3119 }
3120 }
3121 } else if ((cur->type != XML_ELEMENT_NODE) &&
3122 (cur->type != XML_CDATA_SECTION_NODE)) {
3123 delete = cur;
3124 goto skip_children;
3125 }
3126
3127 /*
3128 * Skip to next node
3129 */
3130 if (cur->children != NULL) {
3131 if ((cur->children->type != XML_ENTITY_DECL) &&
3132 (cur->children->type != XML_ENTITY_REF_NODE) &&
3133 (cur->children->type != XML_ENTITY_NODE)) {
3134 cur = cur->children;
3135 continue;
3136 }
3137 }
3138 skip_children:
3139 if (cur->next != NULL) {
3140 cur = cur->next;
3141 continue;
3142 }
3143
3144 do {
3145 cur = cur->parent;
3146 if (cur == NULL)
3147 break;
3148 if (cur == root) {
3149 cur = NULL;
3150 break;
3151 }
3152 if (cur->next != NULL) {
3153 cur = cur->next;
3154 break;
3155 }
3156 } while (cur != NULL);
3157 }
3158 if (delete != NULL) {
3159 xmlUnlinkNode(delete);
3160 xmlFreeNode(delete);
3161 delete = NULL;
3162 }
3163}
3164
3165/**
3166 * xmlSchemaParseSchemaTopLevel:
3167 * @ctxt: a schema validation context
3168 * @schema: the schemas
3169 * @nodes: the list of top level nodes
3170 *
3171 * Returns the internal XML Schema structure built from the resource or
3172 * NULL in case of error
3173 */
3174static void
3175xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
3176 xmlSchemaPtr schema, xmlNodePtr nodes)
3177{
3178 xmlNodePtr child;
3179 xmlSchemaAnnotPtr annot;
3180
3181 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
3182 return;
3183
3184 child = nodes;
3185 while ((IS_SCHEMA(child, "include")) ||
3186 (IS_SCHEMA(child, "import")) ||
3187 (IS_SCHEMA(child, "redefine")) ||
3188 (IS_SCHEMA(child, "annotation"))) {
3189 if (IS_SCHEMA(child, "annotation")) {
3190 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3191 if (schema->annot == NULL)
3192 schema->annot = annot;
3193 else
3194 xmlSchemaFreeAnnot(annot);
3195 } else if (IS_SCHEMA(child, "import")) {
3196 xmlSchemaParseImport(ctxt, schema, child);
3197 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003198 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003199 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003200 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003201 } else if (IS_SCHEMA(child, "redefine")) {
3202 TODO
3203 }
3204 child = child->next;
3205 }
3206 while (child != NULL) {
3207 if (IS_SCHEMA(child, "complexType")) {
3208 xmlSchemaParseComplexType(ctxt, schema, child);
3209 child = child->next;
3210 } else if (IS_SCHEMA(child, "simpleType")) {
3211 xmlSchemaParseSimpleType(ctxt, schema, child);
3212 child = child->next;
3213 } else if (IS_SCHEMA(child, "element")) {
3214 xmlSchemaParseElement(ctxt, schema, child, 1);
3215 child = child->next;
3216 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003217 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003218 child = child->next;
3219 } else if (IS_SCHEMA(child, "attributeGroup")) {
3220 xmlSchemaParseAttributeGroup(ctxt, schema, child);
3221 child = child->next;
3222 } else if (IS_SCHEMA(child, "group")) {
3223 xmlSchemaParseGroup(ctxt, schema, child);
3224 child = child->next;
3225 } else if (IS_SCHEMA(child, "notation")) {
3226 xmlSchemaParseNotation(ctxt, schema, child);
3227 child = child->next;
3228 } else {
3229 xmlSchemaPErr2(ctxt, NULL, child,
3230 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3231 "Schemas: unexpected element %s here \n",
3232 child->name, NULL);
3233 child = child->next;
3234 }
3235 while (IS_SCHEMA(child, "annotation")) {
3236 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3237 if (schema->annot == NULL)
3238 schema->annot = annot;
3239 else
3240 xmlSchemaFreeAnnot(annot);
3241 child = child->next;
3242 }
3243 }
3244}
3245
3246/**
3247 * xmlSchemaParseInclude:
3248 * @ctxt: a schema validation context
3249 * @schema: the schema being built
3250 * @node: a subtree containing XML Schema informations
3251 *
3252 * parse a XML schema Include definition
3253 *
William M. Bracke7091952004-05-11 15:09:58 +00003254 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003255 * 1 in case of success.
3256 */
3257static int
3258xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3259 xmlNodePtr node)
3260{
3261 xmlNodePtr child = NULL;
3262 const xmlChar *schemaLocation;
3263 xmlURIPtr check;
3264 xmlDocPtr doc;
3265 xmlNodePtr root;
3266 xmlSchemaIncludePtr include;
3267
3268
3269 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3270 return (-1);
3271
3272 /*
3273 * Preliminary step, extract the URI-Reference for the include and
3274 * make an URI from the base.
3275 */
3276 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
3277 if (schemaLocation != NULL) {
3278 xmlChar *base = NULL;
3279 xmlChar *URI = NULL;
3280 check = xmlParseURI((const char *) schemaLocation);
3281 if (check == NULL) {
3282 xmlSchemaPErr2(ctxt, node, child,
3283 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3284 "Include schemaLocation attribute is not an URI: %s\n",
3285 schemaLocation, NULL);
3286 return (-1);
3287 } else {
3288 xmlFreeURI(check);
3289 }
3290 base = xmlNodeGetBase(node->doc, node);
3291 if (base == NULL) {
3292 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3293 } else {
3294 URI = xmlBuildURI(schemaLocation, base);
3295 xmlFree(base);
3296 }
3297 if (URI != NULL) {
3298 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3299 xmlFree(URI);
3300 }
3301 } else {
3302 xmlSchemaPErr2(ctxt, node, child,
3303 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3304 "Include schemaLocation attribute missing\n",
3305 NULL, NULL);
3306 return (-1);
3307 }
3308
3309 child = node->children;
3310 while (IS_SCHEMA(child, "annotation")) {
3311 /*
3312 * the annotations here are simply discarded ...
3313 */
3314 child = child->next;
3315 }
3316 if (child != NULL) {
3317 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3318 "Include has unexpected content\n", NULL, NULL);
3319 return (-1);
3320 }
3321
3322 /*
3323 * First step is to parse the input document into an DOM/Infoset
3324 */
3325 doc = xmlReadFile((const char *) schemaLocation, NULL,
3326 SCHEMAS_PARSE_OPTIONS);
3327 if (doc == NULL) {
3328 xmlSchemaPErr(ctxt, NULL,
3329 XML_SCHEMAP_FAILED_LOAD,
3330 "xmlSchemaParse: could not load %s\n",
3331 ctxt->URL, NULL);
3332 return(-1);
3333 }
3334
3335 /*
3336 * Then extract the root of the schema
3337 */
3338 root = xmlDocGetRootElement(doc);
3339 if (root == NULL) {
3340 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3341 XML_SCHEMAP_NOROOT,
3342 "schemas %s has no root", schemaLocation, NULL);
3343 xmlFreeDoc(doc);
3344 return (-1);
3345 }
3346
3347 /*
3348 * Remove all the blank text nodes
3349 */
3350 xmlSchemaCleanupDoc(ctxt, root);
3351
3352 /*
3353 * Check the schemas top level element
3354 */
3355 if (!IS_SCHEMA(root, "schema")) {
3356 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3357 XML_SCHEMAP_NOT_SCHEMA,
3358 "File %s is not a schemas", schemaLocation, NULL);
3359 xmlFreeDoc(doc);
3360 return (-1);
3361 }
3362
3363 /*
3364 * register the include
3365 */
3366 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3367 if (include == NULL) {
3368 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3369 xmlFreeDoc(doc);
3370 return (-1);
3371 }
3372
3373 memset(include, 0, sizeof(xmlSchemaInclude));
3374 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3375 include->doc = doc;
3376 include->next = schema->includes;
3377 schema->includes = include;
3378
3379
3380 /*
3381 * parse the declarations in the included file like if they
3382 * were in the original file.
3383 */
3384 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3385
3386 return (1);
3387}
3388
3389/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003390 * xmlSchemaParseChoice:
3391 * @ctxt: a schema validation context
3392 * @schema: the schema being built
3393 * @node: a subtree containing XML Schema informations
3394 *
3395 * parse a XML schema Choice definition
3396 * *WARNING* this interface is highly subject to change
3397 *
William M. Bracke7091952004-05-11 15:09:58 +00003398 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003399 * 1 in case of success.
3400 */
3401static xmlSchemaTypePtr
3402xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003403 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003404{
3405 xmlSchemaTypePtr type, subtype, last = NULL;
3406 xmlNodePtr child = NULL;
3407 xmlChar name[30];
3408
3409 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3410 return (NULL);
3411
3412
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003413 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003414 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003415 if (type == NULL)
3416 return (NULL);
3417 type->node = node;
3418 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003419 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003420 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3421 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3422
3423 child = node->children;
3424 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003425 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3426 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003427 }
3428 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003429 (IS_SCHEMA(child, "group")) ||
3430 (IS_SCHEMA(child, "any")) ||
3431 (IS_SCHEMA(child, "choice")) ||
3432 (IS_SCHEMA(child, "sequence"))) {
3433 subtype = NULL;
3434 if (IS_SCHEMA(child, "element")) {
3435 subtype = (xmlSchemaTypePtr)
3436 xmlSchemaParseElement(ctxt, schema, child, 0);
3437 } else if (IS_SCHEMA(child, "group")) {
3438 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3439 } else if (IS_SCHEMA(child, "any")) {
3440 subtype = xmlSchemaParseAny(ctxt, schema, child);
3441 } else if (IS_SCHEMA(child, "sequence")) {
3442 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3443 } else if (IS_SCHEMA(child, "choice")) {
3444 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3445 }
3446 if (subtype != NULL) {
3447 if (last == NULL) {
3448 type->subtypes = subtype;
3449 last = subtype;
3450 } else {
3451 last->next = subtype;
3452 last = subtype;
3453 }
3454 last->next = NULL;
3455 }
3456 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003457 }
3458 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003459 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3460 "Choice %s has unexpected content\n", type->name,
3461 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003462 }
3463
3464 return (type);
3465}
3466
3467/**
3468 * xmlSchemaParseSequence:
3469 * @ctxt: a schema validation context
3470 * @schema: the schema being built
3471 * @node: a subtree containing XML Schema informations
3472 *
3473 * parse a XML schema Sequence definition
3474 * *WARNING* this interface is highly subject to change
3475 *
William M. Bracke7091952004-05-11 15:09:58 +00003476 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003477 * 1 in case of success.
3478 */
3479static xmlSchemaTypePtr
3480xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003481 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003482{
3483 xmlSchemaTypePtr type, subtype, last = NULL;
3484 xmlNodePtr child = NULL;
3485 xmlChar name[30];
3486
3487 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3488 return (NULL);
3489
3490
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003491 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003492 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003493 if (type == NULL)
3494 return (NULL);
3495 type->node = node;
3496 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003497 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003498 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3499 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3500
3501 child = node->children;
3502 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003503 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3504 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003505 }
3506 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003507 (IS_SCHEMA(child, "group")) ||
3508 (IS_SCHEMA(child, "any")) ||
3509 (IS_SCHEMA(child, "choice")) ||
3510 (IS_SCHEMA(child, "sequence"))) {
3511 subtype = NULL;
3512 if (IS_SCHEMA(child, "element")) {
3513 subtype = (xmlSchemaTypePtr)
3514 xmlSchemaParseElement(ctxt, schema, child, 0);
3515 } else if (IS_SCHEMA(child, "group")) {
3516 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3517 } else if (IS_SCHEMA(child, "any")) {
3518 subtype = xmlSchemaParseAny(ctxt, schema, child);
3519 } else if (IS_SCHEMA(child, "choice")) {
3520 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3521 } else if (IS_SCHEMA(child, "sequence")) {
3522 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3523 }
3524 if (subtype != NULL) {
3525 if (last == NULL) {
3526 type->subtypes = subtype;
3527 last = subtype;
3528 } else {
3529 last->next = subtype;
3530 last = subtype;
3531 }
3532 last->next = NULL;
3533 }
3534 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003535 }
3536 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003537 xmlSchemaPErr2(ctxt, node, child,
3538 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3539 "Sequence %s has unexpected content\n", type->name,
3540 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003541 }
3542
3543 return (type);
3544}
3545
3546/**
3547 * xmlSchemaParseRestriction:
3548 * @ctxt: a schema validation context
3549 * @schema: the schema being built
3550 * @node: a subtree containing XML Schema informations
3551 * @simple: is that part of a simple type.
3552 *
3553 * parse a XML schema Restriction definition
3554 * *WARNING* this interface is highly subject to change
3555 *
3556 * Returns the type definition or NULL in case of error
3557 */
3558static xmlSchemaTypePtr
3559xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3560 xmlNodePtr node, int simple)
3561{
3562 xmlSchemaTypePtr type, subtype;
3563 xmlSchemaFacetPtr facet, lastfacet = NULL;
3564 xmlNodePtr child = NULL;
3565 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003566 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003567
3568 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3569 return (NULL);
3570
3571 oldcontainer = ctxt->container;
3572
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003573 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003574 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003575 if (type == NULL)
3576 return (NULL);
3577 type->node = node;
3578 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003579 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003580 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3581 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003582 xmlSchemaPErr2(ctxt, node, child,
3583 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
3584 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003585 }
3586 ctxt->container = name;
3587
3588 child = node->children;
3589 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003590 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3591 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003592 }
3593 subtype = NULL;
3594
3595 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003596 subtype = (xmlSchemaTypePtr)
3597 xmlSchemaParseAll(ctxt, schema, child);
3598 child = child->next;
3599 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003600 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003601 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3602 child = child->next;
3603 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003604 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003605 subtype = (xmlSchemaTypePtr)
3606 xmlSchemaParseSequence(ctxt, schema, child);
3607 child = child->next;
3608 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003609 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003610 subtype = (xmlSchemaTypePtr)
3611 xmlSchemaParseGroup(ctxt, schema, child);
3612 child = child->next;
3613 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003615 if (IS_SCHEMA(child, "simpleType")) {
3616 subtype = (xmlSchemaTypePtr)
3617 xmlSchemaParseSimpleType(ctxt, schema, child);
3618 child = child->next;
3619 type->baseType = subtype;
3620 }
3621 /*
3622 * Facets
3623 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003624 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003625 (IS_SCHEMA(child, "minExclusive")) ||
3626 (IS_SCHEMA(child, "maxInclusive")) ||
3627 (IS_SCHEMA(child, "maxExclusive")) ||
3628 (IS_SCHEMA(child, "totalDigits")) ||
3629 (IS_SCHEMA(child, "fractionDigits")) ||
3630 (IS_SCHEMA(child, "pattern")) ||
3631 (IS_SCHEMA(child, "enumeration")) ||
3632 (IS_SCHEMA(child, "whiteSpace")) ||
3633 (IS_SCHEMA(child, "length")) ||
3634 (IS_SCHEMA(child, "maxLength")) ||
3635 (IS_SCHEMA(child, "minLength"))) {
3636 facet = xmlSchemaParseFacet(ctxt, schema, child);
3637 if (facet != NULL) {
3638 if (lastfacet == NULL) {
3639 type->facets = facet;
3640 lastfacet = facet;
3641 } else {
3642 lastfacet->next = facet;
3643 lastfacet = facet;
3644 }
3645 lastfacet->next = NULL;
3646 }
3647 child = child->next;
3648 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003649 }
3650 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3651 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003652 xmlSchemaPErr2(ctxt, node, child,
3653 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
3654 "Restriction %s has unexpected content\n",
3655 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003656 }
3657 ctxt->container = oldcontainer;
3658 return (type);
3659}
3660
3661/**
3662 * xmlSchemaParseExtension:
3663 * @ctxt: a schema validation context
3664 * @schema: the schema being built
3665 * @node: a subtree containing XML Schema informations
3666 *
3667 * parse a XML schema Extension definition
3668 * *WARNING* this interface is highly subject to change
3669 *
3670 * Returns the type definition or NULL in case of error
3671 */
3672static xmlSchemaTypePtr
3673xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003674 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003675{
3676 xmlSchemaTypePtr type, subtype;
3677 xmlNodePtr child = NULL;
3678 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003679 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003680
3681 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3682 return (NULL);
3683
3684 oldcontainer = ctxt->container;
3685
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003686 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003687 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003688 if (type == NULL)
3689 return (NULL);
3690 type->node = node;
3691 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003692 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003693 ctxt->container = name;
3694
3695 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3696 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003697 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3698 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003699 }
3700 child = node->children;
3701 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003702 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3703 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003704 }
3705 subtype = NULL;
3706
3707 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003708 subtype = xmlSchemaParseAll(ctxt, schema, child);
3709 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003710 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003711 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3712 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003713 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003714 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3715 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003716 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003717 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3718 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003719 }
3720 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003721 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003722 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3723 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003724 xmlSchemaPErr2(ctxt, node, child,
3725 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3726 "Extension %s has unexpected content\n", type->name,
3727 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003728 }
3729 ctxt->container = oldcontainer;
3730 return (type);
3731}
3732
3733/**
3734 * xmlSchemaParseSimpleContent:
3735 * @ctxt: a schema validation context
3736 * @schema: the schema being built
3737 * @node: a subtree containing XML Schema informations
3738 *
3739 * parse a XML schema SimpleContent definition
3740 * *WARNING* this interface is highly subject to change
3741 *
3742 * Returns the type definition or NULL in case of error
3743 */
3744static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003745xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3746 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003747{
3748 xmlSchemaTypePtr type, subtype;
3749 xmlNodePtr child = NULL;
3750 xmlChar name[30];
3751
3752 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3753 return (NULL);
3754
3755
William M. Bracke7091952004-05-11 15:09:58 +00003756 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003757 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003758 if (type == NULL)
3759 return (NULL);
3760 type->node = node;
3761 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003762 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003763
3764 child = node->children;
3765 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003766 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3767 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003768 }
3769 subtype = NULL;
3770 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003771 subtype = (xmlSchemaTypePtr)
3772 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3773 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003774 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003775 subtype = (xmlSchemaTypePtr)
3776 xmlSchemaParseExtension(ctxt, schema, child);
3777 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003778 }
3779 type->subtypes = subtype;
3780 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003781 xmlSchemaPErr2(ctxt, node, child,
3782 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3783 "SimpleContent %s has unexpected content\n",
3784 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003785 }
3786 return (type);
3787}
3788
3789/**
3790 * xmlSchemaParseComplexContent:
3791 * @ctxt: a schema validation context
3792 * @schema: the schema being built
3793 * @node: a subtree containing XML Schema informations
3794 *
3795 * parse a XML schema ComplexContent definition
3796 * *WARNING* this interface is highly subject to change
3797 *
3798 * Returns the type definition or NULL in case of error
3799 */
3800static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003801xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3802 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003803{
3804 xmlSchemaTypePtr type, subtype;
3805 xmlNodePtr child = NULL;
3806 xmlChar name[30];
3807
3808 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3809 return (NULL);
3810
3811
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003812 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003813 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003814 if (type == NULL)
3815 return (NULL);
3816 type->node = node;
3817 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003818 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003819
3820 child = node->children;
3821 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003822 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3823 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003824 }
3825 subtype = NULL;
3826 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003827 subtype = (xmlSchemaTypePtr)
3828 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3829 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003830 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003831 subtype = (xmlSchemaTypePtr)
3832 xmlSchemaParseExtension(ctxt, schema, child);
3833 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003834 }
3835 type->subtypes = subtype;
3836 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003837 xmlSchemaPErr2(ctxt, node, child,
3838 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3839 "ComplexContent %s has unexpected content\n",
3840 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003841 }
3842 return (type);
3843}
3844
3845/**
3846 * xmlSchemaParseComplexType:
3847 * @ctxt: a schema validation context
3848 * @schema: the schema being built
3849 * @node: a subtree containing XML Schema informations
3850 *
3851 * parse a XML schema Complex Type definition
3852 * *WARNING* this interface is highly subject to change
3853 *
3854 * Returns the type definition or NULL in case of error
3855 */
3856static xmlSchemaTypePtr
3857xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3858 xmlNodePtr node)
3859{
3860 xmlSchemaTypePtr type, subtype;
3861 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003862 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00003863 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003864 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003865
3866 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3867 return (NULL);
3868
3869 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003870 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003871 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003872
William M. Bracke7091952004-05-11 15:09:58 +00003873 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003874 name = (const xmlChar *)buf;
3875 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3876 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003877
William M. Bracke7091952004-05-11 15:09:58 +00003878 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
3879 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003880 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003881 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003882 return (NULL);
3883 }
Daniel Veillard1aefc862004-03-04 11:40:48 +00003884
William M. Bracke7091952004-05-11 15:09:58 +00003885 if (xmlGetBooleanProp(ctxt, node, "mixed", 0))
3886 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00003887
Daniel Veillard4255d502002-04-16 15:50:10 +00003888 type->node = node;
3889 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003890 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003891 ctxt->container = name;
3892
3893 child = node->children;
3894 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003895 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3896 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003897 }
3898 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00003899 /* 3.4.3 : 2.2
3900 * Specifying mixed='true' when the <simpleContent>
3901 * alternative is chosen has no effect
3902 */
3903 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
3904 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003905 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3906 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003907 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003908 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3909 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003910 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003911 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003912
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003913 if (IS_SCHEMA(child, "all")) {
3914 subtype = xmlSchemaParseAll(ctxt, schema, child);
3915 child = child->next;
3916 } else if (IS_SCHEMA(child, "choice")) {
3917 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3918 child = child->next;
3919 } else if (IS_SCHEMA(child, "sequence")) {
3920 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3921 child = child->next;
3922 } else if (IS_SCHEMA(child, "group")) {
3923 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3924 child = child->next;
3925 }
3926 if (subtype != NULL)
3927 type->subtypes = subtype;
3928 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003929 }
3930 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003931 xmlSchemaPErr2(ctxt, node, child,
3932 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3933 "ComplexType %s has unexpected content\n",
3934 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003935 }
3936 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003937 return (type);
3938}
3939
Daniel Veillard4255d502002-04-16 15:50:10 +00003940/**
3941 * xmlSchemaParseSchema:
3942 * @ctxt: a schema validation context
3943 * @node: a subtree containing XML Schema informations
3944 *
3945 * parse a XML schema definition from a node set
3946 * *WARNING* this interface is highly subject to change
3947 *
3948 * Returns the internal XML Schema structure built from the resource or
3949 * NULL in case of error
3950 */
3951static xmlSchemaPtr
3952xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3953{
3954 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003955 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003956 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003957 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003958
3959 if ((ctxt == NULL) || (node == NULL))
3960 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00003961
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003962 nberrors = ctxt->nberrors;
3963 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003964 if (IS_SCHEMA(node, "schema")) {
3965 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003966 if (schema == NULL)
3967 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003968 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3969 if (val != NULL) {
3970 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3971 } else {
3972 schema->targetNamespace = NULL;
3973 }
3974 schema->id = xmlSchemaGetProp(ctxt, node, "id");
3975 schema->version = xmlSchemaGetProp(ctxt, node, "version");
3976 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003977 if (val != NULL) {
3978 if (xmlStrEqual(val, BAD_CAST "qualified"))
3979 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3980 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3981 xmlSchemaPErr2(ctxt, node, child,
3982 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3983 "Invalid value %s for elementFormDefault\n",
3984 val, NULL);
3985 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003986 } else {
3987 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3988 }
3989 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003990 if (val != NULL) {
3991 if (xmlStrEqual(val, BAD_CAST "qualified"))
3992 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3993 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3994 xmlSchemaPErr2(ctxt, node, child,
3995 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3996 "Invalid value %s for attributeFormDefault\n",
3997 val, NULL);
3998 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003999 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004000
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004001 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
4002 } else {
4003 xmlDocPtr doc;
4004
4005 doc = node->doc;
4006
4007 if ((doc != NULL) && (doc->URL != NULL)) {
4008 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4009 XML_SCHEMAP_NOT_SCHEMA,
4010 "File %s is not a schemas", doc->URL, NULL);
4011 } else {
4012 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4013 XML_SCHEMAP_NOT_SCHEMA,
4014 "File is not a schemas", NULL, NULL);
4015 }
4016 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004017 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004018 if (ctxt->nberrors != 0) {
4019 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004020 xmlSchemaFree(schema);
4021 schema = NULL;
4022 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004023 }
4024 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004025#ifdef DEBUG
4026 if (schema == NULL)
4027 xmlGenericError(xmlGenericErrorContext,
4028 "xmlSchemaParse() failed\n");
4029#endif
4030
4031 return (schema);
4032}
4033
4034/************************************************************************
4035 * *
4036 * Validating using Schemas *
4037 * *
4038 ************************************************************************/
4039
4040/************************************************************************
4041 * *
4042 * Reading/Writing Schemas *
4043 * *
4044 ************************************************************************/
4045
4046/**
4047 * xmlSchemaNewParserCtxt:
4048 * @URL: the location of the schema
4049 *
4050 * Create an XML Schemas parse context for that file/resource expected
4051 * to contain an XML Schemas file.
4052 *
4053 * Returns the parser context or NULL in case of error
4054 */
4055xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004056xmlSchemaNewParserCtxt(const char *URL)
4057{
Daniel Veillard4255d502002-04-16 15:50:10 +00004058 xmlSchemaParserCtxtPtr ret;
4059
4060 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004061 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004062
4063 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4064 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004065 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4066 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004067 return (NULL);
4068 }
4069 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004070 ret->dict = xmlDictCreate();
4071 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004072 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004073 return (ret);
4074}
4075
4076/**
Daniel Veillard6045c902002-10-09 21:13:59 +00004077 * xmlSchemaNewMemParserCtxt:
4078 * @buffer: a pointer to a char array containing the schemas
4079 * @size: the size of the array
4080 *
4081 * Create an XML Schemas parse context for that memory buffer expected
4082 * to contain an XML Schemas file.
4083 *
4084 * Returns the parser context or NULL in case of error
4085 */
4086xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004087xmlSchemaNewMemParserCtxt(const char *buffer, int size)
4088{
Daniel Veillard6045c902002-10-09 21:13:59 +00004089 xmlSchemaParserCtxtPtr ret;
4090
4091 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004092 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00004093
4094 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4095 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004096 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4097 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00004098 return (NULL);
4099 }
4100 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4101 ret->buffer = buffer;
4102 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00004103 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00004104 return (ret);
4105}
4106
4107/**
Daniel Veillard9d751502003-10-29 13:21:47 +00004108 * xmlSchemaNewDocParserCtxt:
4109 * @doc: a preparsed document tree
4110 *
4111 * Create an XML Schemas parse context for that document.
4112 * NB. The document may be modified during the parsing process.
4113 *
4114 * Returns the parser context or NULL in case of error
4115 */
4116xmlSchemaParserCtxtPtr
4117xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
4118{
4119 xmlSchemaParserCtxtPtr ret;
4120
4121 if (doc == NULL)
4122 return (NULL);
4123
4124 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4125 if (ret == NULL) {
4126 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
4127 NULL);
4128 return (NULL);
4129 }
4130 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4131 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00004132 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00004133 /* The application has responsibility for the document */
4134 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00004135
4136 return (ret);
4137}
4138
4139/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004140 * xmlSchemaFreeParserCtxt:
4141 * @ctxt: the schema parser context
4142 *
4143 * Free the resources associated to the schema parser context
4144 */
4145void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004146xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
4147{
Daniel Veillard4255d502002-04-16 15:50:10 +00004148 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004149 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004150 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004151 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004152 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004153 xmlFree(ctxt);
4154}
4155
4156/************************************************************************
4157 * *
4158 * Building the content models *
4159 * *
4160 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004161
Daniel Veillard4255d502002-04-16 15:50:10 +00004162/**
4163 * xmlSchemaBuildAContentModel:
4164 * @type: the schema type definition
4165 * @ctxt: the schema parser context
4166 * @name: the element name whose content is being built
4167 *
4168 * Generate the automata sequence needed for that type
4169 */
4170static void
4171xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004172 xmlSchemaParserCtxtPtr ctxt,
4173 const xmlChar * name)
4174{
Daniel Veillard4255d502002-04-16 15:50:10 +00004175 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004176 xmlGenericError(xmlGenericErrorContext,
4177 "Found unexpected type = NULL in %s content model\n",
4178 name);
4179 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004180 }
4181 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004182 case XML_SCHEMA_TYPE_ANY:
4183 /* TODO : handle the namespace too */
4184 /* TODO : make that a specific transition type */
4185 TODO ctxt->state =
4186 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
4187 BAD_CAST "*", NULL);
4188 break;
4189 case XML_SCHEMA_TYPE_ELEMENT:{
4190 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00004191
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004192 /* TODO : handle the namespace too */
4193 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004194
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004195 if (elem->maxOccurs >= UNBOUNDED) {
4196 if (elem->minOccurs > 1) {
4197 xmlAutomataStatePtr tmp;
4198 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00004199
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004200 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4201 oldstate,
4202 NULL);
4203 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004204
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004205 counter = xmlAutomataNewCounter(ctxt->am,
4206 elem->minOccurs -
4207 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00004208
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004209 if (elem->refDecl != NULL) {
4210 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4211 elem->refDecl,
4212 ctxt,
4213 elem->refDecl->
4214 name);
4215 } else {
4216 ctxt->state =
4217 xmlAutomataNewTransition(ctxt->am,
4218 ctxt->state, NULL,
4219 elem->name, type);
4220 }
4221 tmp = ctxt->state;
4222 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4223 counter);
4224 ctxt->state =
4225 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4226 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00004227
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004228 } else {
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 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4242 oldstate);
4243 if (elem->minOccurs == 0) {
4244 /* basically an elem* */
4245 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4246 ctxt->state);
4247 }
4248 }
4249 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
4250 xmlAutomataStatePtr tmp;
4251 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00004252
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004253 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4254 oldstate, NULL);
4255 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004256
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004257 counter = xmlAutomataNewCounter(ctxt->am,
4258 elem->minOccurs - 1,
4259 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004260
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004261 if (elem->refDecl != NULL) {
4262 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4263 elem->refDecl, ctxt,
4264 elem->refDecl->name);
4265 } else {
4266 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4267 ctxt->state,
4268 NULL,
4269 elem->name,
4270 type);
4271 }
4272 tmp = ctxt->state;
4273 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4274 counter);
4275 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
4276 NULL,
4277 counter);
4278 if (elem->minOccurs == 0) {
4279 /* basically an elem? */
4280 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4281 ctxt->state);
4282 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00004283
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004284 } else {
4285 if (elem->refDecl != NULL) {
4286 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4287 elem->refDecl, ctxt,
4288 elem->refDecl->name);
4289 } else {
4290 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4291 ctxt->state,
4292 NULL,
4293 elem->name,
4294 type);
4295 }
4296 if (elem->minOccurs == 0) {
4297 /* basically an elem? */
4298 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4299 ctxt->state);
4300 }
4301 }
4302 break;
4303 }
4304 case XML_SCHEMA_TYPE_SEQUENCE:{
4305 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004306
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004307 /*
4308 * If max and min occurances are default (1) then
4309 * simply iterate over the subtypes
4310 */
4311 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4312 subtypes = type->subtypes;
4313 while (subtypes != NULL) {
4314 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4315 subtypes = subtypes->next;
4316 }
4317 } else {
4318 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004319
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004320 if (type->maxOccurs >= UNBOUNDED) {
4321 if (type->minOccurs > 1) {
4322 xmlAutomataStatePtr tmp;
4323 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004324
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004325 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4326 oldstate,
4327 NULL);
4328 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004329
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004330 counter = xmlAutomataNewCounter(ctxt->am,
4331 type->
4332 minOccurs - 1,
4333 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004334
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004335 subtypes = type->subtypes;
4336 while (subtypes != NULL) {
4337 xmlSchemaBuildAContentModel(subtypes, ctxt,
4338 name);
4339 subtypes = subtypes->next;
4340 }
4341 tmp = ctxt->state;
4342 xmlAutomataNewCountedTrans(ctxt->am, tmp,
4343 oldstate, counter);
4344 ctxt->state =
4345 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4346 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004347
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004348 } else {
4349 subtypes = type->subtypes;
4350 while (subtypes != NULL) {
4351 xmlSchemaBuildAContentModel(subtypes, ctxt,
4352 name);
4353 subtypes = subtypes->next;
4354 }
4355 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4356 oldstate);
4357 if (type->minOccurs == 0) {
4358 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4359 ctxt->state);
4360 }
4361 }
4362 } else if ((type->maxOccurs > 1)
4363 || (type->minOccurs > 1)) {
4364 xmlAutomataStatePtr tmp;
4365 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004366
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004367 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4368 oldstate,
4369 NULL);
4370 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00004371
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004372 counter = xmlAutomataNewCounter(ctxt->am,
4373 type->minOccurs -
4374 1,
4375 type->maxOccurs -
4376 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004377
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004378 subtypes = type->subtypes;
4379 while (subtypes != NULL) {
4380 xmlSchemaBuildAContentModel(subtypes, ctxt,
4381 name);
4382 subtypes = subtypes->next;
4383 }
4384 tmp = ctxt->state;
4385 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4386 counter);
4387 ctxt->state =
4388 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4389 counter);
4390 if (type->minOccurs == 0) {
4391 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4392 ctxt->state);
4393 }
Daniel Veillardb509f152002-04-17 16:28:10 +00004394
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004395 } else {
4396 subtypes = type->subtypes;
4397 while (subtypes != NULL) {
4398 xmlSchemaBuildAContentModel(subtypes, ctxt,
4399 name);
4400 subtypes = subtypes->next;
4401 }
4402 if (type->minOccurs == 0) {
4403 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4404 ctxt->state);
4405 }
4406 }
4407 }
4408 break;
4409 }
4410 case XML_SCHEMA_TYPE_CHOICE:{
4411 xmlSchemaTypePtr subtypes;
4412 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00004413
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414 start = ctxt->state;
4415 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00004416
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004417 /*
4418 * iterate over the subtypes and remerge the end with an
4419 * epsilon transition
4420 */
4421 if (type->maxOccurs == 1) {
4422 subtypes = type->subtypes;
4423 while (subtypes != NULL) {
4424 ctxt->state = start;
4425 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4426 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4427 subtypes = subtypes->next;
4428 }
4429 } else {
4430 int counter;
4431 xmlAutomataStatePtr hop;
4432 int maxOccurs = type->maxOccurs == UNBOUNDED ?
4433 UNBOUNDED : type->maxOccurs - 1;
4434 int minOccurs =
4435 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00004436
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004437 /*
4438 * use a counter to keep track of the number of transtions
4439 * which went through the choice.
4440 */
4441 counter =
4442 xmlAutomataNewCounter(ctxt->am, minOccurs,
4443 maxOccurs);
4444 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00004445
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004446 subtypes = type->subtypes;
4447 while (subtypes != NULL) {
4448 ctxt->state = start;
4449 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4450 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4451 subtypes = subtypes->next;
4452 }
4453 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4454 counter);
4455 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4456 counter);
4457 }
4458 if (type->minOccurs == 0) {
4459 xmlAutomataNewEpsilon(ctxt->am, start, end);
4460 }
4461 ctxt->state = end;
4462 break;
4463 }
4464 case XML_SCHEMA_TYPE_ALL:{
4465 xmlAutomataStatePtr start;
4466 xmlSchemaTypePtr subtypes;
4467 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4468 int lax;
4469
4470 subtypes = type->subtypes;
4471 if (subtypes == NULL)
4472 break;
4473 start = ctxt->state;
4474 while (subtypes != NULL) {
4475 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00004476 /*
4477 * the following 'if' was needed to fix bug 139897
4478 * not quite sure why it only needs to be done for
4479 * elements with a 'ref', but it seems to work ok.
4480 */
4481 if (subtypes->ref != NULL)
4482 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
William M. Bracke7091952004-05-11 15:09:58 +00004483 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004484 /* TODO : handle the namespace too */
4485 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4486 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4487 ctxt->state, elem->name, 1,
4488 1, subtypes);
4489 } else {
4490 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4491 ctxt->state, elem->name,
4492 elem->minOccurs,
4493 elem->maxOccurs,
4494 subtypes);
4495 }
4496 subtypes = subtypes->next;
4497 }
4498 lax = type->minOccurs == 0;
4499 ctxt->state =
4500 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4501 lax);
4502 break;
4503 }
4504 case XML_SCHEMA_TYPE_RESTRICTION:
4505 if (type->subtypes != NULL)
4506 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4507 break;
4508 case XML_SCHEMA_TYPE_EXTENSION:
4509 if (type->baseType != NULL) {
4510 xmlSchemaTypePtr subtypes;
4511
Daniel Veillardf7627552004-04-22 07:15:40 +00004512 if (type->recurse) {
4513 xmlSchemaPErr(ctxt, type->node,
4514 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4515 "Schemas: extension type %s is recursive\n",
4516 type->name, NULL);
4517 return;
4518 }
4519 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004520 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00004521 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004522 subtypes = type->subtypes;
4523 while (subtypes != NULL) {
4524 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4525 subtypes = subtypes->next;
4526 }
4527 } else if (type->subtypes != NULL)
4528 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4529 break;
4530 case XML_SCHEMA_TYPE_GROUP:
4531 if (type->subtypes == NULL) {
William M. Brack29aa7722004-05-12 00:27:56 +00004532 xmlSchemaTypePtr rgroup;
4533 if (type->ref != NULL) {
4534 rgroup = xmlHashLookup2(ctxt->schema->groupDecl, type->ref,
4535 type->refNs);
4536 if (rgroup == NULL) {
4537 xmlSchemaPErr(ctxt, type->node,
4538 XML_SCHEMAP_UNKNOWN_REF,
4539 "Schemas: group %s reference %s is not found",
4540 name, type->ref);
4541 return;
4542 }
4543 xmlSchemaBuildAContentModel(rgroup, ctxt, name);
4544 break;
4545 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004546 }
4547 case XML_SCHEMA_TYPE_COMPLEX:
4548 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4549 if (type->subtypes != NULL)
4550 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4551 break;
4552 default:
4553 xmlGenericError(xmlGenericErrorContext,
4554 "Found unexpected type %d in %s content model\n",
4555 type->type, name);
4556 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004557 }
4558}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004559
Daniel Veillard4255d502002-04-16 15:50:10 +00004560/**
4561 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004562 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00004563 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004564 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00004565 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004566 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00004567 */
4568static void
4569xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004570 xmlSchemaParserCtxtPtr ctxt,
4571 const xmlChar * name)
4572{
Daniel Veillard4255d502002-04-16 15:50:10 +00004573 xmlAutomataStatePtr start;
4574
Daniel Veillard4255d502002-04-16 15:50:10 +00004575 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004576 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004577 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004578 elem->contentType = XML_SCHEMA_CONTENT_ANY;
4579 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004580 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004581 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004582 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004583 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
4584 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004585 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004586
4587#ifdef DEBUG_CONTENT
4588 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004589 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004590#endif
4591
Daniel Veillard4255d502002-04-16 15:50:10 +00004592 ctxt->am = xmlNewAutomata();
4593 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004594 xmlGenericError(xmlGenericErrorContext,
4595 "Cannot create automata for elem %s\n", name);
4596 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004597 }
4598 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
4599 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
4600 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00004601 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004602 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004603 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
4604 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004605 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004606 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
4607 "Content model of %s is not determinist:\n", name,
4608 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00004609 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00004610#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004611 xmlGenericError(xmlGenericErrorContext,
4612 "Content model of %s:\n", name);
4613 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004614#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00004615 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004616 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004617 xmlFreeAutomata(ctxt->am);
4618 ctxt->am = NULL;
4619}
4620
4621/**
4622 * xmlSchemaRefFixupCallback:
4623 * @elem: the schema element context
4624 * @ctxt: the schema parser context
4625 *
4626 * Free the resources associated to the schema parser context
4627 */
4628static void
4629xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004630 xmlSchemaParserCtxtPtr ctxt,
4631 const xmlChar * name,
4632 const xmlChar * context ATTRIBUTE_UNUSED,
4633 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004634{
4635 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004636 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004637 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004638 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004639
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004640 if (elem->subtypes != NULL) {
4641 xmlSchemaPErr(ctxt, elem->node,
4642 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
4643 "Schemas: element %s have both ref and subtype\n",
4644 name, NULL);
4645 return;
4646 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004647 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004648
4649 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004650 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
4651 "Schemas: element %s ref to %s not found\n",
4652 name, elem->ref);
4653 return;
4654 }
4655 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004656 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004657 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004658
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004659 if (elem->subtypes != NULL) {
4660 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
4661 "Schemas: element %s have both type and subtype\n",
4662 name, NULL);
4663 return;
4664 }
4665 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
4666 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00004667
4668 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004669 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
4670 "Schemas: element %s type %s not found\n", name,
4671 elem->namedType);
4672 return;
4673 }
4674 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004675 }
4676}
4677
William M. Bracke7091952004-05-11 15:09:58 +00004678/**
4679 * xmlSchemaParseListRefFixup:
4680 * @type: the schema type definition
4681 * @ctxt: the schema parser context
4682 *
4683 * Fixup of the itemType reference of the list type.
4684 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00004685static void
William M. Bracke7091952004-05-11 15:09:58 +00004686xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
4687{
4688 const xmlChar *itemType, *namespace;
4689 xmlSchemaTypePtr subtype;
4690
4691 /* Handle the "itemType" attribute. */
William M. Brack29aa7722004-05-12 00:27:56 +00004692 itemType = xmlGetQNameProp(ctxt, type->node, "itemType", &namespace);
William M. Bracke7091952004-05-11 15:09:58 +00004693 if (itemType != NULL) {
4694 /* Do not allow more that one item type. */
4695 if (type->subtypes != NULL) {
4696 xmlSchemaPErr(ctxt, type->node,
4697 XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE,
4698 "List %s has more than one item type defined\n",
4699 type->name, NULL);
4700 }
4701 subtype = xmlSchemaGetType(ctxt->schema, itemType, namespace);
4702 if (subtype == NULL) {
4703 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_TYPE,
4704 "List %s references an unknown item type: %s\n",
4705 type->name, xmlSchemaGetProp(ctxt, type->node,
William M. Brack29aa7722004-05-12 00:27:56 +00004706 "itemType"));
William M. Bracke7091952004-05-11 15:09:58 +00004707 } else
4708 type->subtypes = subtype;
4709 }
4710}
4711
4712/**
4713 * xmlSchemaParseUnionRefCheck:
4714 * @typeDecl: the schema type definition
4715 * @ctxt: the schema parser context
4716 *
4717 * Checks the memberTypes references of the union type.
4718 */
4719static void
4720xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00004721 xmlSchemaParserCtxtPtr ctxt)
4722{
4723 const xmlChar *cur, *end, *prefix, *ncName, *namespace;
4724 xmlChar *tmp;
4725 xmlSchemaTypePtr subtype;
4726 xmlNsPtr ns;
4727 int len;
4728
William M. Bracke7091952004-05-11 15:09:58 +00004729 if ((type->type != XML_SCHEMA_TYPE_UNION) || (type->ref == NULL))
Daniel Veillard377e1a92004-04-16 16:30:05 +00004730 return;
4731
William M. Bracke7091952004-05-11 15:09:58 +00004732 cur = type->ref;
Daniel Veillard377e1a92004-04-16 16:30:05 +00004733 do {
4734 while (IS_BLANK_CH(*cur))
4735 cur++;
4736 end = cur;
4737 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4738 end++;
4739 if (end == cur)
4740 break;
4741 tmp = xmlStrndup(cur, end - cur);
4742 ncName = xmlSplitQName3(tmp, &len);
4743 if (ncName != NULL) {
4744 prefix = xmlDictLookup(ctxt->dict, tmp, len);
4745 } else {
4746 prefix = NULL;
4747 ncName = tmp;
4748 }
William M. Bracke7091952004-05-11 15:09:58 +00004749 ns = xmlSearchNs(type->node->doc, type->node, prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004750 if (ns == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00004751 if (prefix != NULL) {
4752 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_PREFIX_UNDEFINED,
4753 "Union %s: the namespace prefix of member type "
4754 "%s is undefined\n",
4755 type->name, (const xmlChar *) tmp);
4756 }
4757 namespace = NULL;
Daniel Veillard377e1a92004-04-16 16:30:05 +00004758 } else {
4759 namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4760 }
4761 /* Lookup the referenced type */
4762 subtype = xmlSchemaGetType(ctxt->schema, ncName, namespace);
4763 if (subtype == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00004764 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
4765 "Union %s references an unknown member type %s\n",
4766 type->name, (const xmlChar *) tmp);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004767 }
William M. Bracke7091952004-05-11 15:09:58 +00004768 xmlFree(tmp);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004769 cur = end;
William M. Bracke7091952004-05-11 15:09:58 +00004770 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004771}
4772
Daniel Veillard4255d502002-04-16 15:50:10 +00004773/**
4774 * xmlSchemaTypeFixup:
4775 * @typeDecl: the schema type definition
4776 * @ctxt: the schema parser context
4777 *
4778 * Fixes the content model of the type.
4779 */
4780static void
4781xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004782 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004783{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00004784 if (typeDecl == NULL)
4785 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004786 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004787 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004788 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004789 switch (typeDecl->type) {
4790 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4791 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4792 if (typeDecl->subtypes != NULL)
4793 typeDecl->contentType =
4794 typeDecl->subtypes->contentType;
4795 break;
4796 }
4797 case XML_SCHEMA_TYPE_RESTRICTION:{
4798 if (typeDecl->subtypes != NULL)
4799 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004800
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004801 if (typeDecl->base != NULL) {
4802 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004803
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004804 baseType =
4805 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4806 typeDecl->baseNs);
4807 if (baseType == NULL) {
4808 xmlSchemaPErr(ctxt, typeDecl->node,
4809 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004810 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004811 name, typeDecl->base);
4812 }
4813 typeDecl->baseType = baseType;
4814 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004815 if (typeDecl->subtypes == NULL)
William M. Bracke7091952004-05-11 15:09:58 +00004816 if (typeDecl->baseType != NULL) {
4817 /* The base type might be not "type fixed" yet,
4818 * so do it now. */
4819 if (typeDecl->baseType->contentType ==
4820 XML_SCHEMA_CONTENT_UNKNOWN)
4821 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004822 typeDecl->contentType =
4823 typeDecl->baseType->contentType;
William M. Bracke7091952004-05-11 15:09:58 +00004824 } else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004825 /* 1.1.1 */
4826 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004827 else if ((typeDecl->subtypes->subtypes == NULL) &&
4828 ((typeDecl->subtypes->type ==
4829 XML_SCHEMA_TYPE_ALL)
4830 || (typeDecl->subtypes->type ==
4831 XML_SCHEMA_TYPE_SEQUENCE)))
4832 /* 1.1.2 */
4833 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4834 else if ((typeDecl->subtypes->type ==
4835 XML_SCHEMA_TYPE_CHOICE)
4836 && (typeDecl->subtypes->subtypes == NULL))
4837 /* 1.1.3 */
4838 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4839 else {
4840 /* 1.2 and 2.X are applied at the other layer */
4841 typeDecl->contentType =
4842 XML_SCHEMA_CONTENT_ELEMENTS;
4843 }
4844 break;
4845 }
4846 case XML_SCHEMA_TYPE_EXTENSION:{
4847 xmlSchemaContentType explicitContentType;
4848 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004849
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004850 if (typeDecl->base != NULL) {
4851 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004852
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004853 baseType =
4854 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4855 typeDecl->baseNs);
4856 if (baseType == NULL) {
4857 xmlSchemaPErr(ctxt, typeDecl->node,
4858 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004859 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004860 name, typeDecl->base);
4861 }
4862 typeDecl->baseType = baseType;
4863 }
4864 if (typeDecl->subtypes != NULL)
4865 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004866
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004867 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4868 if (typeDecl->subtypes == NULL)
4869 /* 1.1.1 */
4870 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4871 else if ((typeDecl->subtypes->subtypes == NULL) &&
4872 ((typeDecl->subtypes->type ==
4873 XML_SCHEMA_TYPE_ALL)
4874 || (typeDecl->subtypes->type ==
4875 XML_SCHEMA_TYPE_SEQUENCE)))
4876 /* 1.1.2 */
4877 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4878 else if ((typeDecl->subtypes->type ==
4879 XML_SCHEMA_TYPE_CHOICE)
4880 && (typeDecl->subtypes->subtypes == NULL))
4881 /* 1.1.3 */
4882 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004883
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004884 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4885 typeDecl->baseNs);
4886 if (base == NULL) {
4887 xmlSchemaPErr(ctxt, typeDecl->node,
4888 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4889 "Schemas: base type %s of type %s not found\n",
4890 typeDecl->base, name);
4891 return;
4892 }
Daniel Veillard2582a332004-04-18 19:49:46 +00004893 if (typeDecl->recurse) {
4894 xmlSchemaPErr(ctxt, typeDecl->node,
4895 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4896 "Schemas: extension type %s is recursive\n",
4897 name, NULL);
4898 return;
4899 }
4900 typeDecl->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004901 xmlSchemaTypeFixup(base, ctxt, NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +00004902 typeDecl->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004903 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4904 /* 2.1 */
4905 typeDecl->contentType = base->contentType;
4906 } else if (base->contentType ==
4907 XML_SCHEMA_CONTENT_EMPTY) {
4908 /* 2.2 imbitable ! */
4909 typeDecl->contentType =
4910 XML_SCHEMA_CONTENT_ELEMENTS;
4911 } else {
4912 /* 2.3 imbitable pareil ! */
4913 typeDecl->contentType =
4914 XML_SCHEMA_CONTENT_ELEMENTS;
4915 }
4916 break;
4917 }
4918 case XML_SCHEMA_TYPE_COMPLEX:{
4919 if (typeDecl->subtypes == NULL) {
4920 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004921
4922 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4923 typeDecl->contentType =
4924 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004925 } else {
4926 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4927 typeDecl->contentType =
4928 XML_SCHEMA_CONTENT_MIXED;
4929 else {
4930 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4931 NULL);
4932 if (typeDecl->subtypes != NULL)
4933 typeDecl->contentType =
4934 typeDecl->subtypes->contentType;
4935 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004936 if (typeDecl->attributes == NULL)
4937 typeDecl->attributes =
4938 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004939 }
4940 break;
4941 }
4942 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4943 if (typeDecl->subtypes == NULL) {
4944 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004945 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4946 typeDecl->contentType =
4947 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004948 } else {
4949 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4950 typeDecl->contentType =
4951 XML_SCHEMA_CONTENT_MIXED;
4952 else {
4953 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4954 NULL);
4955 if (typeDecl->subtypes != NULL)
4956 typeDecl->contentType =
4957 typeDecl->subtypes->contentType;
4958 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004959 if (typeDecl->attributes == NULL)
4960 typeDecl->attributes =
4961 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004962 }
4963 break;
4964 }
4965 case XML_SCHEMA_TYPE_SEQUENCE:
4966 case XML_SCHEMA_TYPE_GROUP:
4967 case XML_SCHEMA_TYPE_ALL:
4968 case XML_SCHEMA_TYPE_CHOICE:
4969 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4970 break;
4971 case XML_SCHEMA_TYPE_BASIC:
4972 case XML_SCHEMA_TYPE_ANY:
4973 case XML_SCHEMA_TYPE_FACET:
4974 case XML_SCHEMA_TYPE_SIMPLE:
4975 case XML_SCHEMA_TYPE_UR:
4976 case XML_SCHEMA_TYPE_ELEMENT:
4977 case XML_SCHEMA_TYPE_ATTRIBUTE:
4978 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +00004979 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004980 case XML_SCHEMA_TYPE_NOTATION:
4981 case XML_SCHEMA_TYPE_LIST:
William M. Bracke7091952004-05-11 15:09:58 +00004982 xmlSchemaParseListRefFixup(typeDecl, ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004983 case XML_SCHEMA_TYPE_UNION:
Daniel Veillard377e1a92004-04-16 16:30:05 +00004984 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004985 case XML_SCHEMA_FACET_MININCLUSIVE:
4986 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4987 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4988 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4989 case XML_SCHEMA_FACET_TOTALDIGITS:
4990 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4991 case XML_SCHEMA_FACET_PATTERN:
4992 case XML_SCHEMA_FACET_ENUMERATION:
4993 case XML_SCHEMA_FACET_WHITESPACE:
4994 case XML_SCHEMA_FACET_LENGTH:
4995 case XML_SCHEMA_FACET_MAXLENGTH:
4996 case XML_SCHEMA_FACET_MINLENGTH:
4997 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004998 if (typeDecl->subtypes != NULL)
4999 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005000 break;
5001 }
5002 }
Daniel Veillard8651f532002-04-17 09:06:27 +00005003#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005004 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005005 xmlGenericError(xmlGenericErrorContext,
5006 "Type of %s : %s:%d :", name,
5007 typeDecl->node->doc->URL,
5008 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005009 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005010 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005011 }
Daniel Veillard8651f532002-04-17 09:06:27 +00005012 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005013 case XML_SCHEMA_CONTENT_SIMPLE:
5014 xmlGenericError(xmlGenericErrorContext, "simple\n");
5015 break;
5016 case XML_SCHEMA_CONTENT_ELEMENTS:
5017 xmlGenericError(xmlGenericErrorContext, "elements\n");
5018 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005019 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005020 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
5021 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005022 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005023 xmlGenericError(xmlGenericErrorContext, "empty\n");
5024 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005025 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005026 xmlGenericError(xmlGenericErrorContext, "mixed\n");
5027 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005028 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005029 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
5030 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005031 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005032 xmlGenericError(xmlGenericErrorContext, "basic\n");
5033 break;
5034 default:
5035 xmlGenericError(xmlGenericErrorContext,
5036 "not registered !!!\n");
5037 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005038 }
5039#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00005040}
5041
5042/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005043 * xmlSchemaCheckFacet:
5044 * @facet: the facet
5045 * @typeDecl: the schema type definition
5046 * @ctxt: the schema parser context or NULL
5047 * @name: name of the type
5048 *
5049 * Checks the default values types, especially for facets
5050 *
5051 * Returns 0 if okay or -1 in cae of error
5052 */
5053int
5054xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005055 xmlSchemaTypePtr typeDecl,
5056 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005057{
5058 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
5059 int ret = 0;
5060
5061 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005062 nonNegativeIntegerType =
5063 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
5064 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005065 }
5066 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005067 case XML_SCHEMA_FACET_MININCLUSIVE:
5068 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5069 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5070 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
5071 /*
5072 * Okay we need to validate the value
5073 * at that point.
5074 */
5075 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005076
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005077 vctxt = xmlSchemaNewValidCtxt(NULL);
5078 if (vctxt == NULL)
5079 break;
5080 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
5081 facet->value);
5082 facet->val = vctxt->value;
5083 vctxt->value = NULL;
5084 if (facet->val == NULL) {
5085 /* error code */
5086 if (ctxt != NULL) {
5087 xmlSchemaPErr(ctxt, facet->node,
5088 XML_SCHEMAP_INVALID_FACET,
5089 "Schemas: type %s facet value %s invalid\n",
5090 name, facet->value);
5091 }
5092 ret = -1;
5093 }
5094 xmlSchemaFreeValidCtxt(vctxt);
5095 break;
5096 }
5097 case XML_SCHEMA_FACET_ENUMERATION:{
5098 /*
5099 * Okay we need to validate the value
5100 * at that point.
5101 */
5102 xmlSchemaValidCtxtPtr vctxt;
5103 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005104
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005105 vctxt = xmlSchemaNewValidCtxt(NULL);
5106 if (vctxt == NULL)
5107 break;
5108 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
5109 facet->value);
5110 if (tmp != 0) {
5111 if (ctxt != NULL) {
5112 xmlSchemaPErr(ctxt, facet->node,
5113 XML_SCHEMAP_INVALID_ENUM,
5114 "Schemas: type %s enumeration value %s invalid\n",
5115 name, facet->value);
5116 }
5117 ret = -1;
5118 }
5119 xmlSchemaFreeValidCtxt(vctxt);
5120 break;
5121 }
5122 case XML_SCHEMA_FACET_PATTERN:
5123 facet->regexp = xmlRegexpCompile(facet->value);
5124 if (facet->regexp == NULL) {
5125 xmlSchemaPErr(ctxt, typeDecl->node,
5126 XML_SCHEMAP_REGEXP_INVALID,
5127 "Schemas: type %s facet regexp %s invalid\n",
5128 name, facet->value);
5129 ret = -1;
5130 }
5131 break;
5132 case XML_SCHEMA_FACET_TOTALDIGITS:
5133 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5134 case XML_SCHEMA_FACET_LENGTH:
5135 case XML_SCHEMA_FACET_MAXLENGTH:
5136 case XML_SCHEMA_FACET_MINLENGTH:{
5137 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005138
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005139 tmp =
5140 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
5141 facet->value,
5142 &facet->val);
5143 if (tmp != 0) {
5144 /* error code */
5145 if (ctxt != NULL) {
5146 xmlSchemaPErr(ctxt, facet->node,
5147 XML_SCHEMAP_INVALID_FACET_VALUE,
5148 "Schemas: type %s facet value %s invalid\n",
5149 name, facet->value);
5150 }
5151 ret = -1;
5152 }
5153 break;
5154 }
5155 case XML_SCHEMA_FACET_WHITESPACE:{
5156 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
5157 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
5158 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
5159 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
5160 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
5161 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
5162 } else {
5163 if (ctxt != NULL) {
5164 xmlSchemaPErr(ctxt, facet->node,
5165 XML_SCHEMAP_INVALID_WHITE_SPACE,
5166 "Schemas: type %s whiteSpace value %s invalid\n",
5167 name, facet->value);
5168 }
5169 ret = -1;
5170 }
5171 }
5172 default:
5173 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005174 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005175 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005176}
5177
5178/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005179 * xmlSchemaCheckDefaults:
5180 * @typeDecl: the schema type definition
5181 * @ctxt: the schema parser context
5182 *
5183 * Checks the default values types, especially for facets
5184 */
5185static void
5186xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005187 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00005188{
Daniel Veillard4255d502002-04-16 15:50:10 +00005189 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005190 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005191 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005192 if (typeDecl->facets != NULL) {
5193 xmlSchemaFacetPtr facet = typeDecl->facets;
5194
5195 while (facet != NULL) {
5196 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
5197 facet = facet->next;
5198 }
5199 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005200 }
5201}
5202
5203/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00005204 * xmlSchemaAttrGrpFixup:
5205 * @attrgrpDecl: the schema attribute definition
5206 * @ctxt: the schema parser context
5207 * @name: the attribute name
5208 *
5209 * Fixes finish doing the computations on the attributes definitions
5210 */
5211static void
5212xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005213 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00005214{
5215 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005216 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005217 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005218 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005219 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005220 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005221
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005222 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
5223 attrgrpDecl->refNs);
5224 if (ref == NULL) {
5225 xmlSchemaPErr(ctxt, attrgrpDecl->node,
5226 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
5227 "Schemas: attribute group %s reference %s not found\n",
5228 name, attrgrpDecl->ref);
5229 return;
5230 }
5231 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
5232 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005233 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005234 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
5235 "Schemas: attribute %s has no attributes nor reference\n",
5236 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00005237 }
5238}
5239
5240/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005241 * xmlSchemaAttrFixup:
5242 * @attrDecl: the schema attribute definition
5243 * @ctxt: the schema parser context
5244 * @name: the attribute name
5245 *
5246 * Fixes finish doing the computations on the attributes definitions
5247 */
5248static void
5249xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005250 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00005251{
5252 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005253 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005254 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005255 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005256 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005257 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005258
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005259 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
5260 attrDecl->typeNs);
5261 if (type == NULL) {
5262 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
5263 "Schemas: attribute %s type %s not found\n",
5264 name, attrDecl->typeName);
5265 }
5266 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005267 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005268 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00005269
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005270 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
5271 attrDecl->refNs);
5272 if (ref == NULL) {
5273 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
5274 "Schemas: attribute %s reference %s not found\n",
5275 name, attrDecl->ref);
5276 return;
5277 }
5278 xmlSchemaAttrFixup(ref, ctxt, NULL);
5279 attrDecl->subtypes = ref->subtypes;
William M. Bracke7091952004-05-11 15:09:58 +00005280 } else if (attrDecl->type != XML_SCHEMA_TYPE_ANY_ATTRIBUTE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005281 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
5282 "Schemas: attribute %s has no type nor reference\n",
5283 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005284 }
5285}
5286
5287/**
5288 * xmlSchemaParse:
5289 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00005290 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00005291 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00005292 * XML Shema struture which can be used to validate instances.
5293 * *WARNING* this interface is highly subject to change
5294 *
5295 * Returns the internal XML Schema structure built from the resource or
5296 * NULL in case of error
5297 */
5298xmlSchemaPtr
5299xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
5300{
5301 xmlSchemaPtr ret = NULL;
5302 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005303 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005304 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005305 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005306
5307 xmlSchemaInitTypes();
5308
Daniel Veillard6045c902002-10-09 21:13:59 +00005309 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00005310 return (NULL);
5311
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005312 nberrors = ctxt->nberrors;
5313 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005314 ctxt->counter = 0;
5315 ctxt->container = NULL;
5316
5317 /*
5318 * First step is to parse the input document into an DOM/Infoset
5319 */
Daniel Veillard6045c902002-10-09 21:13:59 +00005320 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005321 doc = xmlReadFile((const char *) ctxt->URL, NULL,
5322 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005323 if (doc == NULL) {
5324 xmlSchemaPErr(ctxt, NULL,
5325 XML_SCHEMAP_FAILED_LOAD,
5326 "xmlSchemaParse: could not load %s\n",
5327 ctxt->URL, NULL);
5328 return (NULL);
5329 }
Daniel Veillard6045c902002-10-09 21:13:59 +00005330 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005331 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
5332 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005333 if (doc == NULL) {
5334 xmlSchemaPErr(ctxt, NULL,
5335 XML_SCHEMAP_FAILED_PARSE,
5336 "xmlSchemaParse: could not parse\n",
5337 NULL, NULL);
5338 return (NULL);
5339 }
5340 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00005341 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00005342 } else if (ctxt->doc != NULL) {
5343 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005344 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00005345 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005346 xmlSchemaPErr(ctxt, NULL,
5347 XML_SCHEMAP_NOTHING_TO_PARSE,
5348 "xmlSchemaParse: could not parse\n",
5349 NULL, NULL);
5350 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005351 }
5352
5353 /*
5354 * Then extract the root and Schema parse it
5355 */
5356 root = xmlDocGetRootElement(doc);
5357 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005358 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
5359 XML_SCHEMAP_NOROOT,
5360 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00005361 if (!preserve) {
5362 xmlFreeDoc(doc);
5363 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005364 return (NULL);
5365 }
5366
5367 /*
5368 * Remove all the blank text nodes
5369 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005370 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00005371
5372 /*
5373 * Then do the parsing for good
5374 */
5375 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00005376 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00005377 if (!preserve) {
5378 xmlFreeDoc(doc);
5379 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005380 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00005381 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005382 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005383 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00005384
5385 /*
5386 * Then fix all the references.
5387 */
5388 ctxt->schema = ret;
5389 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005390 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005391
5392 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005393 * Then fixup all attributes declarations
5394 */
5395 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
5396
5397 /*
5398 * Then fixup all attributes group declarations
5399 */
5400 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
5401 ctxt);
5402
5403 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00005404 * Then fixup all types properties
5405 */
5406 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
5407
5408 /*
5409 * Then build the content model for all elements
5410 */
5411 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005412 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005413
5414 /*
5415 * Then check the defaults part of the type like facets values
5416 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005417 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
5418 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005419
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005420 if (ctxt->nberrors != 0) {
5421 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005422 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005423 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005424 return (ret);
5425}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005426
Daniel Veillard4255d502002-04-16 15:50:10 +00005427/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00005428 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00005429 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00005430 * @err: the error callback
5431 * @warn: the warning callback
5432 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00005433 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00005434 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00005435 */
5436void
5437xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005438 xmlSchemaValidityErrorFunc err,
5439 xmlSchemaValidityWarningFunc warn, void *ctx)
5440{
Daniel Veillard4255d502002-04-16 15:50:10 +00005441 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005442 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005443 ctxt->error = err;
5444 ctxt->warning = warn;
5445 ctxt->userData = ctx;
5446}
5447
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005448/**
5449 * xmlSchemaFacetTypeToString:
5450 * @type: the facet type
5451 *
5452 * Convert the xmlSchemaTypeType to a char string.
5453 *
5454 * Returns the char string representation of the facet type if the
5455 * type is a facet and an "Internal Error" string otherwise.
5456 */
5457static const char *
5458xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5459{
5460 switch (type) {
5461 case XML_SCHEMA_FACET_PATTERN:
5462 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005463 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005464 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005465 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005466 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005467 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005468 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005469 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005470 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005471 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005472 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005473 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005474 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005475 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005476 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005477 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005478 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005479 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005480 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005481 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005482 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005483 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005484 return ("fractionDigits");
5485 default:
5486 break;
5487 }
5488 return ("Internal Error");
5489}
5490
5491/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00005492 * xmlSchemaValidateFacetsInternal:
5493 * @ctxt: a schema validation context
5494 * @base: the base type
5495 * @facets: the list of facets to check
5496 * @value: the lexical repr of the value to validate
5497 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +00005498 * @fireErrors: if 0, only internal errors will be fired;
5499 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00005500 *
5501 * Check a value against all facet conditions
5502 *
5503 * Returns 0 if the element is schemas valid, a positive error code
5504 * number otherwise and -1 in case of internal or API error.
5505 */
5506static int
5507xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
5508 xmlSchemaTypePtr base,
William M. Bracke7091952004-05-11 15:09:58 +00005509 xmlSchemaFacetPtr facets,
5510 const xmlChar * value, int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00005511{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005512 int ret = 0;
5513 int tmp = 0;
5514 xmlSchemaTypeType type;
5515 xmlSchemaFacetPtr facet = facets;
5516
5517 while (facet != NULL) {
5518 type = facet->type;
5519 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005520 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005521
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005522 while (facet != NULL) {
5523 tmp =
5524 xmlSchemaValidateFacet(base, facet, value,
5525 ctxt->value);
5526 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005527 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005528 }
5529 facet = facet->next;
5530 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005531 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005532 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005533
5534 if (tmp != 0) {
5535 ret = tmp;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005536 if (fireErrors)
William M. Bracke7091952004-05-11 15:09:58 +00005537 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET,
5538 "Failed to validate type with facet %s\n",
5539 (const xmlChar *) xmlSchemaFacetTypeToString(type),
5540 NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005541 }
5542 if (facet != NULL)
5543 facet = facet->next;
5544 }
5545 return (ret);
5546}
5547
William M. Brack87640d52004-04-17 14:58:15 +00005548/**
5549 * xmlSchemaValidateFacets:
5550 * @ctxt: a schema validation context
5551 * @base: the base type
5552 * @facets: the list of facets to check
5553 * @value: the lexical repr of the value to validate
5554 * @val: the precomputed value
5555 *
5556 * Check a value against all facet conditions
5557 *
5558 * Returns 0 if the element is schemas valid, a positive error code
5559 * number otherwise and -1 in case of internal or API error.
5560 */
5561static int
5562xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5563 xmlSchemaTypePtr base,
5564 xmlSchemaFacetPtr facets, const xmlChar * value)
5565{
5566 return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
5567}
5568
Daniel Veillard4255d502002-04-16 15:50:10 +00005569/************************************************************************
5570 * *
5571 * Simple type validation *
5572 * *
5573 ************************************************************************/
5574
5575/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00005576 * xmlSchemaValidateSimpleValueUnion:
5577 * @ctxt: a schema validation context
5578 * @type: the type declaration
5579 * @value: the value to validate
5580 *
5581 * Validates a value against a union.
5582 *
5583 * Returns 0 if the value is valid, a positive error code
5584 * number otherwise and -1 in case of internal or API error.
5585 */
5586static int
5587xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
5588 xmlSchemaTypePtr type, const xmlChar * value)
5589{
5590 int ret = 0;
5591 const xmlChar *cur, *end, *prefix, *ncName;
5592 xmlChar *tmp;
5593 xmlSchemaTypePtr subtype;
5594 xmlNsPtr ns;
5595 int len;
5596
5597
5598 /* Process referenced memberTypes. */
5599 cur = type->ref;
5600 do {
5601 while (IS_BLANK_CH(*cur))
5602 cur++;
5603 end = cur;
5604 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5605 end++;
5606 if (end == cur)
5607 break;
5608 tmp = xmlStrndup(cur, end - cur);
5609 ncName = xmlSplitQName3(tmp, &len);
5610 if (ncName != NULL) {
5611 prefix = xmlStrndup(tmp, len);
5612 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
5613 } else {
5614 prefix = NULL;
5615 ncName = tmp;
5616 }
William M. Bracke7091952004-05-11 15:09:58 +00005617 /* We won't do additional checks here,
5618 * since they have been performed during parsing. */
Daniel Veillard377e1a92004-04-16 16:30:05 +00005619 ns = xmlSearchNs(type->node->doc, type->node, prefix);
5620 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
5621 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
5622 if (tmp != NULL)
5623 xmlFree(tmp);
5624 if (prefix != NULL)
William M. Brack87640d52004-04-17 14:58:15 +00005625 xmlFree((void *)prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005626 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5627 if ((ret == 0) || (ret == -1)) {
5628 return (ret);
5629 }
5630 cur = end;
5631 } while (*cur != 0);
5632
5633 if (type->subtypes != NULL) {
5634 subtype = type->subtypes;
5635 do {
5636 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5637 if ((ret == 0) || (ret == -1)) {
5638 return (ret);
5639 }
5640 subtype = subtype->next;
5641 } while (subtype != NULL);
5642 }
5643 return (ret);
5644}
5645
5646/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005647 * xmlSchemaValidateSimpleValue:
5648 * @ctxt: a schema validation context
5649 * @type: the type declaration
5650 * @value: the value to validate
5651 *
5652 * Validate a value against a simple type
5653 *
5654 * Returns 0 if the value is valid, a positive error code
5655 * number otherwise and -1 in case of internal or API error.
5656 */
5657static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005658xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005659 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005660{
Daniel Veillard377e1a92004-04-16 16:30:05 +00005661 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
5662}
5663
5664/**
5665 * xmlSchemaValidateSimpleValue:
5666 * @ctxt: a schema validation context
5667 * @type: the type declaration
5668 * @value: the value to validate
William M. Bracke7091952004-05-11 15:09:58 +00005669 * @fireErrors: if 0, only internal errors will be fired;
5670 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00005671 *
5672 * Validate a value against a simple type
5673 *
5674 * Returns 0 if the value is valid, a positive error code
5675 * number otherwise and -1 in case of internal or API error.
5676 */
5677static int
5678xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
William M. Bracke7091952004-05-11 15:09:58 +00005679 xmlSchemaTypePtr type,
5680 const xmlChar * value,
5681 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00005682{
Daniel Veillard4255d502002-04-16 15:50:10 +00005683 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005684
Daniel Veillard4255d502002-04-16 15:50:10 +00005685 /*
5686 * First normalize the value accordingly to Schema Datatype
5687 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
William M. Bracke7091952004-05-11 15:09:58 +00005688 *
Daniel Veillard4255d502002-04-16 15:50:10 +00005689 * Then check the normalized value against the lexical space of the
5690 * type.
5691 */
5692 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005693 if (ctxt->value != NULL) {
5694 xmlSchemaFreeValue(ctxt->value);
5695 ctxt->value = NULL;
5696 }
5697 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5698 ctxt->cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005699 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00005700 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
5701 "Failed to validate basic type %s\n",
5702 type->name, NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005703 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005704 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005705 xmlSchemaTypePtr base;
5706 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005707
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005708 base = type->baseType;
5709 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005710 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5711 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005712 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005713 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005714 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005715
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005716 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005717 * Do not validate facets or attributes when working on
5718 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005719 */
5720 if (ctxt->schema != NULL) {
5721 if (ret == 0) {
5722 facet = type->facets;
William M. Bracke7091952004-05-11 15:09:58 +00005723 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet,
5724 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005725 }
5726 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005727 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005728 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00005729
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005730 base = type->subtypes;
5731 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005732 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5733 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005734 } else {
5735 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00005736 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005737 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005738 const xmlChar *cur, *end;
5739 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005740 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00005741
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005742 base = type->subtypes;
5743 if (base == NULL) {
5744 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5745 "Internal: List type %s has no base type\n",
5746 type->name, NULL);
5747 return (-1);
5748 }
5749 cur = value;
5750 do {
William M. Brack76e95df2003-10-18 16:20:14 +00005751 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005752 cur++;
5753 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00005754 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005755 end++;
5756 if (end == cur)
5757 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005758 tmp = xmlStrndup(cur, end - cur);
William M. Bracke7091952004-05-11 15:09:58 +00005759 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5760 tmp, fireErrors);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005761 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005762 if (ret2 != 0)
5763 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005764 cur = end;
5765 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005766 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
5767 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
5768 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00005769 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
5770 "Failed to validate type %s\n", type->name, NULL);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005771 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005772 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005773 TODO
5774 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005775 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005776}
5777
5778/************************************************************************
5779 * *
5780 * DOM Validation code *
5781 * *
5782 ************************************************************************/
5783
5784static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005785 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005786static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005787 xmlNodePtr elem,
5788 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005789static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005790 xmlNodePtr elem,
5791 xmlSchemaElementPtr elemDecl,
5792 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00005793
5794/**
5795 * xmlSchemaRegisterAttributes:
5796 * @ctxt: a schema validation context
5797 * @attrs: a list of attributes
5798 *
5799 * Register the list of attributes as the set to be validated on that element
5800 *
5801 * Returns -1 in case of error, 0 otherwise
5802 */
5803static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005804xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5805{
Daniel Veillard4255d502002-04-16 15:50:10 +00005806 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005807 if ((attrs->ns != NULL) &&
5808 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5809 attrs = attrs->next;
5810 continue;
5811 }
5812 if (ctxt->attrNr >= ctxt->attrMax) {
5813 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00005814
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005815 ctxt->attrMax *= 2;
5816 tmp = (xmlSchemaAttrStatePtr)
5817 xmlRealloc(ctxt->attr, ctxt->attrMax *
5818 sizeof(xmlSchemaAttrState));
5819 if (tmp == NULL) {
5820 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5821 ctxt->attrMax /= 2;
5822 return (-1);
5823 }
5824 ctxt->attr = tmp;
5825 }
5826 ctxt->attr[ctxt->attrNr].attr = attrs;
5827 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5828 ctxt->attrNr++;
5829 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005830 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005831 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005832}
5833
5834/**
5835 * xmlSchemaCheckAttributes:
5836 * @ctxt: a schema validation context
5837 * @node: the node carrying it.
5838 *
5839 * Check that the registered set of attributes on the current node
5840 * has been properly validated.
5841 *
5842 * Returns 0 if validity constraints are met, 1 otherwise.
5843 */
5844static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005845xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5846{
Daniel Veillard4255d502002-04-16 15:50:10 +00005847 int ret = 0;
5848 int i;
5849
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005850 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5851 if (ctxt->attr[i].attr == NULL)
5852 break;
5853 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5854 ret = 1;
William M. Bracke7091952004-05-11 15:09:58 +00005855 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
5856 "Attribute %s on %s is unknown\n",
5857 ctxt->attr[i].attr->name, node->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005858 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005859 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005860 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005861}
5862
William M. Brack29aa7722004-05-12 00:27:56 +00005863#if 0 /* Not currently used - remove if ever needed */
Daniel Veillard4255d502002-04-16 15:50:10 +00005864/**
5865 * xmlSchemaValidateSimpleContent:
5866 * @ctxt: a schema validation context
5867 * @elem: an element
5868 * @type: the type declaration
5869 *
5870 * Validate the content of an element expected to be a simple type
5871 *
5872 * Returns 0 if the element is schemas valid, a positive error code
5873 * number otherwise and -1 in case of internal or API error.
5874 */
5875static int
5876xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005877 xmlNodePtr node ATTRIBUTE_UNUSED)
5878{
Daniel Veillard4255d502002-04-16 15:50:10 +00005879 xmlNodePtr child;
5880 xmlSchemaTypePtr type, base;
5881 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005882 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005883
5884 child = ctxt->node;
5885 type = ctxt->type;
5886
5887 /*
5888 * Validation Rule: Element Locally Valid (Type): 3.1.3
5889 */
5890 value = xmlNodeGetContent(child);
5891 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5892 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005893 case XML_SCHEMA_TYPE_RESTRICTION:{
5894 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005895
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005896 base = type->baseType;
5897 if (base != NULL) {
5898 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5899 } else {
5900 TODO}
5901 if (ret == 0) {
5902 facet = type->facets;
5903 ret =
5904 xmlSchemaValidateFacets(ctxt, base, facet, value);
5905 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005906 if ((ret == 0) && (type->attributes != NULL)) {
5907 ret = xmlSchemaValidateAttributes(ctxt, node,
5908 type->attributes);
5909 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005910 break;
5911 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005912 case XML_SCHEMA_TYPE_EXTENSION:{
5913 TODO
5914 break;
5915 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005916 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005917 TODO
5918 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005919 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005920 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005921
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005922 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005923}
William M. Brack29aa7722004-05-12 00:27:56 +00005924#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00005925
5926/**
5927 * xmlSchemaValidateCheckNodeList
5928 * @nodelist: the list of nodes
5929 *
5930 * Check the node list is only made of text nodes and entities pointing
5931 * to text nodes
5932 *
5933 * Returns 1 if true, 0 if false and -1 in case of error
5934 */
5935static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005936xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5937{
Daniel Veillard4255d502002-04-16 15:50:10 +00005938 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005939 if (nodelist->type == XML_ENTITY_REF_NODE) {
5940 TODO /* implement recursion in the entity content */
5941 }
5942 if ((nodelist->type != XML_TEXT_NODE) &&
5943 (nodelist->type != XML_COMMENT_NODE) &&
5944 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +00005945 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005946 return (0);
5947 }
5948 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005949 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005950 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005951}
5952
5953/**
5954 * xmlSchemaSkipIgnored:
5955 * @ctxt: a schema validation context
5956 * @type: the current type context
5957 * @node: the top node.
5958 *
5959 * Skip ignorable nodes in that context
5960 *
5961 * Returns the new sibling
5962 * number otherwise and -1 in case of internal or API error.
5963 */
5964static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005965xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005966 xmlSchemaTypePtr type, xmlNodePtr node)
5967{
Daniel Veillard4255d502002-04-16 15:50:10 +00005968 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005969
Daniel Veillard4255d502002-04-16 15:50:10 +00005970 /*
5971 * TODO complete and handle entities
5972 */
5973 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005974 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005975 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005976 ((node->type == XML_COMMENT_NODE) ||
5977 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5978 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5979 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5980 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005981 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005982 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005983}
5984
5985/**
5986 * xmlSchemaValidateCallback:
5987 * @ctxt: a schema validation context
5988 * @name: the name of the element detected (might be NULL)
5989 * @type: the type
5990 *
5991 * A transition has been made in the automata associated to an element
5992 * content model
5993 */
5994static void
5995xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005996 const xmlChar * name ATTRIBUTE_UNUSED,
5997 xmlSchemaTypePtr type, xmlNodePtr node)
5998{
Daniel Veillard4255d502002-04-16 15:50:10 +00005999 xmlSchemaTypePtr oldtype = ctxt->type;
6000 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006001
Daniel Veillard4255d502002-04-16 15:50:10 +00006002#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00006003 xmlGenericError(xmlGenericErrorContext,
6004 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006005 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006006#endif
6007 ctxt->type = type;
6008 ctxt->node = node;
6009 xmlSchemaValidateContent(ctxt, node);
6010 ctxt->type = oldtype;
6011 ctxt->node = oldnode;
6012}
6013
6014
6015#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006016
Daniel Veillard4255d502002-04-16 15:50:10 +00006017/**
6018 * xmlSchemaValidateSimpleRestrictionType:
6019 * @ctxt: a schema validation context
6020 * @node: the top node.
6021 *
6022 * Validate the content of a restriction type.
6023 *
6024 * Returns 0 if the element is schemas valid, a positive error code
6025 * number otherwise and -1 in case of internal or API error.
6026 */
6027static int
6028xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
6029 xmlNodePtr node)
6030{
6031 xmlNodePtr child;
6032 xmlSchemaTypePtr type;
6033 int ret;
6034
6035 child = ctxt->node;
6036 type = ctxt->type;
6037
6038 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006039 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6040 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
6041 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006042 return (-1);
6043 }
6044 /*
6045 * Only text and text based entities references shall be found there
6046 */
6047 ret = xmlSchemaValidateCheckNodeList(child);
6048 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006049 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6050 "Internal error: xmlSchemaValidateSimpleType %s content\n",
6051 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006052 return (-1);
6053 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006054 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
6055 "Element %s content is not a simple type\n",
6056 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006057 return (-1);
6058 }
6059 ctxt->type = type->subtypes;
6060 xmlSchemaValidateContent(ctxt, node);
6061 ctxt->type = type;
6062 return (ret);
6063}
6064#endif
6065
6066/**
6067 * xmlSchemaValidateSimpleType:
6068 * @ctxt: a schema validation context
6069 * @node: the top node.
6070 *
6071 * Validate the content of an simple type.
6072 *
6073 * Returns 0 if the element is schemas valid, a positive error code
6074 * number otherwise and -1 in case of internal or API error.
6075 */
6076static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006077xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6078{
Daniel Veillard4255d502002-04-16 15:50:10 +00006079 xmlNodePtr child;
William M. Bracke7091952004-05-11 15:09:58 +00006080 xmlSchemaTypePtr type, base, variety;
Daniel Veillard4255d502002-04-16 15:50:10 +00006081 xmlAttrPtr attr;
6082 int ret;
William M. Bracke7091952004-05-11 15:09:58 +00006083 xmlChar *value;
6084
Daniel Veillard4255d502002-04-16 15:50:10 +00006085
6086 child = ctxt->node;
6087 type = ctxt->type;
6088
6089 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006090 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6091 "Internal error: xmlSchemaValidateSimpleType %s\n",
6092 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006093 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006094 }
6095 /*
6096 * Only text and text based entities references shall be found there
6097 */
6098 ret = xmlSchemaValidateCheckNodeList(child);
6099 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006100 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6101 "Internal error: xmlSchemaValidateSimpleType %s content\n",
6102 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006103 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006104 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006105 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
6106 "Element %s content is not a simple type\n",
6107 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006108 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006109 }
6110 /*
6111 * Validation Rule: Element Locally Valid (Type): 3.1.1
William M. Bracke7091952004-05-11 15:09:58 +00006112 */
6113
Daniel Veillard4255d502002-04-16 15:50:10 +00006114 attr = node->properties;
6115 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006116 if ((attr->ns == NULL) ||
6117 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
6118 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6119 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
6120 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
6121 (!xmlStrEqual
6122 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
William M. Bracke7091952004-05-11 15:09:58 +00006123 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
6124 "Element %s: attribute %s should not be present\n",
6125 node->name, attr->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006126 return (ctxt->err);
6127 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006128 }
William M. Bracke7091952004-05-11 15:09:58 +00006129 /* TODO:
6130 * If {variety} is ·atomic· then the {variety} of {base type definition}
6131 * must be ·atomic·.
6132 * If {variety} is ·list· then the {variety} of {item type definition}
6133 * must be either ·atomic· or ·union·.
6134 * If {variety} is ·union· then {member type definitions} must be a list
6135 * of datatype definitions.
6136 */
6137 if (type->subtypes == NULL) {
6138 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6139 "Internal error: xmlSchemaValidateSimpleType; "
6140 "simple type %s does not define a variety\n",
6141 node->name, NULL);
6142 return (ctxt->err);
6143 }
6144 /* Varieties: Restriction or List or Union. */
6145 variety = type->subtypes;
6146 ctxt->type = variety;
6147 value = xmlNodeGetContent(child);
6148 switch (variety->type) {
6149 case XML_SCHEMA_TYPE_RESTRICTION:{
6150 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00006151
William M. Bracke7091952004-05-11 15:09:58 +00006152 base = variety->baseType;
6153 if (base != NULL) {
6154 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
6155 } else {
6156 TODO}
6157 if (ret == 0) {
6158 facet = variety->facets;
6159 ret =
6160 xmlSchemaValidateFacets(ctxt, base, facet, value);
6161 }
6162 if ((ret == 0) && (variety->attributes != NULL)) {
6163 ret = xmlSchemaValidateAttributes(ctxt, node,
6164 variety->attributes);
6165 }
6166 break;
6167 }
6168 case XML_SCHEMA_TYPE_LIST:
6169 case XML_SCHEMA_TYPE_UNION: {
6170 ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
6171 break;
6172 }
6173 default:{
6174 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6175 "Internal error: xmlSchemaValidateSimpleType; "
6176 "simple type %s defines unknown content: %s\n",
6177 variety->name, NULL);
6178 ret = ctxt->err;
6179 }
6180 }
6181 if (value != NULL)
6182 xmlFree(value);
6183
6184 /* This was removed, since a simple content is not a content of a
6185 * simple type, but of a complex type.
6186 * ret = xmlSchemaValidateSimpleContent(ctxt, node);
6187 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006188 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006189 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006190}
6191
6192/**
6193 * xmlSchemaValidateElementType:
6194 * @ctxt: a schema validation context
6195 * @node: the top node.
6196 *
6197 * Validate the content of an element type.
6198 * Validation Rule: Element Locally Valid (Complex Type)
6199 *
6200 * Returns 0 if the element is schemas valid, a positive error code
6201 * number otherwise and -1 in case of internal or API error.
6202 */
6203static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006204xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6205{
Daniel Veillard4255d502002-04-16 15:50:10 +00006206 xmlNodePtr child;
6207 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006208 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00006209 xmlSchemaElementPtr decl;
6210 int ret, attrBase;
6211
6212 oldregexp = ctxt->regexp;
6213
6214 child = ctxt->node;
6215 type = ctxt->type;
6216
6217 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006218 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6219 "Internal error: xmlSchemaValidateElementType\n",
6220 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006221 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006222 }
6223 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006224 if (type->minOccurs > 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006225 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
6226 "Element %s: missing child %s\n",
6227 node->name, type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006228 }
6229 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006230 }
6231
6232 /*
6233 * Verify the element matches
6234 */
6235 if (!xmlStrEqual(child->name, type->name)) {
William M. Bracke7091952004-05-11 15:09:58 +00006236 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
6237 "Element %s: missing child %s found %s\n",
6238 node->name, type->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006239 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006240 }
6241 /*
6242 * Verify the attributes
6243 */
6244 attrBase = ctxt->attrBase;
6245 ctxt->attrBase = ctxt->attrNr;
6246 xmlSchemaRegisterAttributes(ctxt, child->properties);
6247 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
6248 /*
6249 * Verify the element content recursively
6250 */
6251 decl = (xmlSchemaElementPtr) type;
6252 oldregexp = ctxt->regexp;
6253 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006254 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
6255 (xmlRegExecCallbacks)
6256 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006257#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006258 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006259#endif
6260 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006261 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
6262 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00006263
6264 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006265 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006266#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006267 xmlGenericError(xmlGenericErrorContext,
6268 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006269#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006270 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006271 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
6272 "Element %s content check failed\n",
6273 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006274 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006275 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
6276 "Element %s content check failure\n",
6277 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006278#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006279 } else {
6280 xmlGenericError(xmlGenericErrorContext,
6281 "Element %s content check succeeded\n",
6282 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006283
6284#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006285 }
6286 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006287 }
6288 /*
6289 * Verify that all attributes were Schemas-validated
6290 */
6291 xmlSchemaCheckAttributes(ctxt, node);
6292 ctxt->attrNr = ctxt->attrBase;
6293 ctxt->attrBase = attrBase;
6294
6295 ctxt->regexp = oldregexp;
6296
6297 ctxt->node = child;
6298 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006299 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006300}
6301
6302/**
6303 * xmlSchemaValidateBasicType:
6304 * @ctxt: a schema validation context
6305 * @node: the top node.
6306 *
6307 * Validate the content of an element expected to be a basic type type
6308 *
6309 * Returns 0 if the element is schemas valid, a positive error code
6310 * number otherwise and -1 in case of internal or API error.
6311 */
6312static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006313xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6314{
Daniel Veillard4255d502002-04-16 15:50:10 +00006315 int ret;
6316 xmlNodePtr child, cur;
6317 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006318 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00006319
6320 child = ctxt->node;
6321 type = ctxt->type;
6322
6323 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006324 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6325 "Internal error: xmlSchemaValidateBasicType\n",
6326 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006327 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006328 }
6329 /*
6330 * First check the content model of the node.
6331 */
6332 cur = child;
6333 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006334 switch (cur->type) {
6335 case XML_TEXT_NODE:
6336 case XML_CDATA_SECTION_NODE:
6337 case XML_PI_NODE:
6338 case XML_COMMENT_NODE:
6339 case XML_XINCLUDE_START:
6340 case XML_XINCLUDE_END:
6341 break;
6342 case XML_ENTITY_REF_NODE:
6343 case XML_ENTITY_NODE:
6344 TODO break;
6345 case XML_ELEMENT_NODE:
William M. Bracke7091952004-05-11 15:09:58 +00006346 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
6347 "Element %s: child %s should not be present\n",
6348 node->name, cur->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006349 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006350 case XML_ATTRIBUTE_NODE:
6351 case XML_DOCUMENT_NODE:
6352 case XML_DOCUMENT_TYPE_NODE:
6353 case XML_DOCUMENT_FRAG_NODE:
6354 case XML_NOTATION_NODE:
6355 case XML_HTML_DOCUMENT_NODE:
6356 case XML_DTD_NODE:
6357 case XML_ELEMENT_DECL:
6358 case XML_ATTRIBUTE_DECL:
6359 case XML_ENTITY_DECL:
6360 case XML_NAMESPACE_DECL:
6361#ifdef LIBXML_DOCB_ENABLED
6362 case XML_DOCB_DOCUMENT_NODE:
6363#endif
William M. Bracke7091952004-05-11 15:09:58 +00006364 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
6365 "Element %s: node type of node unexpected here\n",
6366 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006367 return (ctxt->err);
6368 }
6369 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006370 }
6371 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006372 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006373 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006374 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00006375
6376 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006377 xmlSchemaFreeValue(ctxt->value);
6378 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006379 }
6380 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
6381 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006382 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00006383 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006384 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
6385 "Element %s: failed to validate basic type %s\n",
6386 node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006387 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006388 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006389}
6390
6391/**
6392 * xmlSchemaValidateComplexType:
6393 * @ctxt: a schema validation context
6394 * @node: the top node.
6395 *
6396 * Validate the content of an element expected to be a complex type type
6397 * xmlschema-1.html#cvc-complex-type
6398 * Validation Rule: Element Locally Valid (Complex Type)
6399 *
6400 * Returns 0 if the element is schemas valid, a positive error code
6401 * number otherwise and -1 in case of internal or API error.
6402 */
6403static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006404xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6405{
Daniel Veillard4255d502002-04-16 15:50:10 +00006406 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00006407 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006408 int ret;
6409
6410 child = ctxt->node;
6411 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006412 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00006413
Daniel Veillard4255d502002-04-16 15:50:10 +00006414 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006415 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006416 if (type->baseType != NULL) {
6417 } else if (child != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006418 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY,
6419 "Element %s is supposed to be empty\n",
6420 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006421 }
6422 if (type->attributes != NULL) {
6423 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6424 }
6425 subtype = type->subtypes;
6426 while (subtype != NULL) {
6427 ctxt->type = subtype;
6428 xmlSchemaValidateComplexType(ctxt, node);
6429 subtype = subtype->next;
6430 }
6431 break;
6432 case XML_SCHEMA_CONTENT_ELEMENTS:
6433 case XML_SCHEMA_CONTENT_MIXED:
6434 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
6435 /*
6436 * Skip ignorable nodes in that context
6437 */
6438 child = xmlSchemaSkipIgnored(ctxt, type, child);
6439 while (child != NULL) {
6440 if (child->type == XML_ELEMENT_NODE) {
6441 ret = xmlRegExecPushString(ctxt->regexp,
6442 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00006443#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006444 if (ret < 0)
6445 xmlGenericError(xmlGenericErrorContext,
6446 " --> %s Error\n", child->name);
6447 else
6448 xmlGenericError(xmlGenericErrorContext,
6449 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006450#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006451 }
6452 child = child->next;
6453 /*
6454 * Skip ignorable nodes in that context
6455 */
6456 child = xmlSchemaSkipIgnored(ctxt, type, child);
6457 }
William M. Bracke7091952004-05-11 15:09:58 +00006458 if (((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
6459 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS)) &&
6460 (type->subtypes != NULL)) {
6461 TODO
6462 }
6463
6464
Daniel Veillardf2a12832003-11-24 13:04:35 +00006465 if (type->attributes != NULL) {
6466 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6467 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006468 break;
6469 case XML_SCHEMA_CONTENT_BASIC:{
6470 if (type->subtypes != NULL) {
6471 ctxt->type = type->subtypes;
6472 xmlSchemaValidateComplexType(ctxt, node);
6473 }
6474 if (type->baseType != NULL) {
6475 ctxt->type = type->baseType;
William M. Bracke7091952004-05-11 15:09:58 +00006476 if (type->baseType->type == XML_SCHEMA_TYPE_BASIC)
6477 xmlSchemaValidateBasicType(ctxt, node);
6478 else if (type->baseType->type == XML_SCHEMA_TYPE_COMPLEX)
6479 xmlSchemaValidateComplexType(ctxt, node);
6480 else if (type->baseType->type == XML_SCHEMA_TYPE_SIMPLE)
6481 xmlSchemaValidateSimpleType(ctxt, node);
6482 else
6483 xmlGenericError(xmlGenericErrorContext,
6484 "unexpected content type of base: %d\n",
6485 type->contentType);
6486
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006487 }
6488 if (type->attributes != NULL) {
6489 xmlSchemaValidateAttributes(ctxt, node,
6490 type->attributes);
6491 }
6492 ctxt->type = type;
6493 break;
6494 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006495 case XML_SCHEMA_CONTENT_SIMPLE:{
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 xmlSchemaValidateComplexType(ctxt, node);
6503 }
6504 if (type->attributes != NULL) {
6505 xmlSchemaValidateAttributes(ctxt, node,
6506 type->attributes);
6507 }
6508 ctxt->type = type;
6509 break;
6510 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006511 default:
6512 TODO xmlGenericError(xmlGenericErrorContext,
6513 "unimplemented content type %d\n",
6514 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006515 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006516 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006517}
6518
6519/**
6520 * xmlSchemaValidateContent:
6521 * @ctxt: a schema validation context
6522 * @elem: an element
6523 * @type: the type declaration
6524 *
6525 * Validate the content of an element against the type.
6526 *
6527 * Returns 0 if the element is schemas valid, a positive error code
6528 * number otherwise and -1 in case of internal or API error.
6529 */
6530static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006531xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6532{
Daniel Veillard4255d502002-04-16 15:50:10 +00006533 xmlNodePtr child;
6534 xmlSchemaTypePtr type;
6535
6536 child = ctxt->node;
6537 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006538 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00006539
Daniel Veillarde19fc232002-04-22 16:01:24 +00006540 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006541 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00006542
Daniel Veillard4255d502002-04-16 15:50:10 +00006543 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006544 case XML_SCHEMA_TYPE_ANY:
6545 /* Any type will do it, fine */
6546 TODO /* handle recursivity */
6547 break;
6548 case XML_SCHEMA_TYPE_COMPLEX:
6549 xmlSchemaValidateComplexType(ctxt, node);
6550 break;
6551 case XML_SCHEMA_TYPE_ELEMENT:{
6552 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
6553
6554 /*
6555 * Handle element reference here
6556 */
6557 if (decl->ref != NULL) {
6558 if (decl->refDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006559 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6560 "Internal error: element reference %s "
6561 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006562 return (-1);
6563 }
6564 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
6565 decl = decl->refDecl;
6566 }
William M. Bracke7091952004-05-11 15:09:58 +00006567 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006568 xmlSchemaValidateElementType(ctxt, node);
6569 ctxt->type = type;
6570 break;
6571 }
6572 case XML_SCHEMA_TYPE_BASIC:
6573 xmlSchemaValidateBasicType(ctxt, node);
6574 break;
6575 case XML_SCHEMA_TYPE_FACET:
6576 TODO break;
6577 case XML_SCHEMA_TYPE_SIMPLE:
6578 xmlSchemaValidateSimpleType(ctxt, node);
6579 break;
6580 case XML_SCHEMA_TYPE_SEQUENCE:
6581 TODO break;
6582 case XML_SCHEMA_TYPE_CHOICE:
6583 TODO break;
6584 case XML_SCHEMA_TYPE_ALL:
6585 TODO break;
6586 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
6587 TODO break;
6588 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
6589 TODO break;
6590 case XML_SCHEMA_TYPE_UR:
6591 TODO break;
6592 case XML_SCHEMA_TYPE_RESTRICTION:
6593 /*xmlSchemaValidateRestrictionType(ctxt, node); */
6594 TODO break;
6595 case XML_SCHEMA_TYPE_EXTENSION:
6596 TODO break;
6597 case XML_SCHEMA_TYPE_ATTRIBUTE:
6598 TODO break;
6599 case XML_SCHEMA_TYPE_GROUP:
6600 TODO break;
6601 case XML_SCHEMA_TYPE_NOTATION:
6602 TODO break;
6603 case XML_SCHEMA_TYPE_LIST:
6604 TODO break;
6605 case XML_SCHEMA_TYPE_UNION:
6606 TODO break;
6607 case XML_SCHEMA_FACET_MININCLUSIVE:
6608 TODO break;
6609 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6610 TODO break;
6611 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6612 TODO break;
6613 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
6614 TODO break;
6615 case XML_SCHEMA_FACET_TOTALDIGITS:
6616 TODO break;
6617 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6618 TODO break;
6619 case XML_SCHEMA_FACET_PATTERN:
6620 TODO break;
6621 case XML_SCHEMA_FACET_ENUMERATION:
6622 TODO break;
6623 case XML_SCHEMA_FACET_WHITESPACE:
6624 TODO break;
6625 case XML_SCHEMA_FACET_LENGTH:
6626 TODO break;
6627 case XML_SCHEMA_FACET_MAXLENGTH:
6628 TODO break;
6629 case XML_SCHEMA_FACET_MINLENGTH:
6630 TODO break;
6631 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
6632 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +00006633 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6634 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00006635 }
6636 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6637
6638 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006639 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006640 ctxt->node = ctxt->node->next;
6641 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006642 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006643}
6644
6645/**
6646 * xmlSchemaValidateType:
6647 * @ctxt: a schema validation context
6648 * @elem: an element
6649 * @type: the list of type declarations
6650 *
6651 * Validate the content of an element against the types.
6652 *
6653 * Returns 0 if the element is schemas valid, a positive error code
6654 * number otherwise and -1 in case of internal or API error.
6655 */
6656static int
6657xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006658 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
6659{
Daniel Veillard4255d502002-04-16 15:50:10 +00006660 xmlChar *nil;
6661
Daniel Veillard2db8c122003-07-08 12:16:59 +00006662 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006663 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00006664
Daniel Veillard4255d502002-04-16 15:50:10 +00006665 /*
6666 * 3.3.4 : 2
6667 */
6668 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
William M. Bracke7091952004-05-11 15:09:58 +00006669 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
6670 "Element declaration %s is abstract\n",
6671 elemDecl->name, NULL);
6672 /* Changed, since the element declaration is abstract and not
6673 * the element itself. */
6674 /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
6675 "Element %s is abstract\n", elem->name, NULL); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006676 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006677 }
6678 /*
6679 * 3.3.4: 3
6680 */
6681 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
6682 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006683 /* 3.3.4: 3.2 */
6684 if (xmlStrEqual(nil, BAD_CAST "true")) {
6685 if (elem->children != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006686 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
6687 "Element %s is not empty\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006688 return (ctxt->err);
6689 }
6690 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
6691 (elemDecl->value != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006692 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
6693 "Empty element %s cannot get a fixed value\n",
6694 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006695 return (ctxt->err);
6696 }
6697 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006698 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006699 /* 3.3.4: 3.1 */
6700 if (nil != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006701 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
6702 "Element %s with xs:nil but not nillable\n",
6703 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006704 xmlFree(nil);
6705 return (ctxt->err);
6706 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006707 }
6708
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006709 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00006710
6711 ctxt->type = elemDecl->subtypes;
6712 ctxt->node = elem->children;
6713 xmlSchemaValidateContent(ctxt, elem);
6714 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006715
6716 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006717}
6718
6719
6720/**
6721 * xmlSchemaValidateAttributes:
6722 * @ctxt: a schema validation context
6723 * @elem: an element
6724 * @attributes: the list of attribute declarations
6725 *
6726 * Validate the attributes of an element.
6727 *
6728 * Returns 0 if the element is schemas valid, a positive error code
6729 * number otherwise and -1 in case of internal or API error.
6730 */
6731static int
6732xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006733 xmlSchemaAttributePtr attributes)
6734{
William M. Brack87640d52004-04-17 14:58:15 +00006735 int i, ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006736 xmlAttrPtr attr;
6737 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006738 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006739 int found;
Daniel Veillard4255d502002-04-16 15:50:10 +00006740
6741 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006742 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006743 while (attributes != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006744 found = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006745 /*
6746 * Handle attribute groups
6747 */
6748 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6749 group = (xmlSchemaAttributeGroupPtr) attributes;
6750 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6751 attributes = group->next;
6752 continue;
6753 }
6754 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6755 attr = ctxt->attr[i].attr;
6756 if (attr == NULL)
6757 continue;
6758 if (attributes->ref != NULL) {
6759 if (!xmlStrEqual(attr->name, attributes->ref))
6760 continue;
6761 if (attr->ns != NULL) {
6762 if ((attributes->refNs == NULL) ||
6763 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6764 continue;
6765 } else if (attributes->refNs != NULL) {
6766 continue;
6767 }
6768 } else {
6769 if (!xmlStrEqual(attr->name, attributes->name))
6770 continue;
6771 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006772 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006773 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006774 if (attr->ns == NULL) {
6775 /*
William M. Bracke7091952004-05-11 15:09:58 +00006776 * accept an unqualified attribute only if the target
6777 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006778 */
William M. Bracke7091952004-05-11 15:09:58 +00006779 if (attributes->targetNamespace != NULL)
6780 /*
6781 * This check was removed, since the target namespace
6782 * was evaluated during parsing and already took
6783 * "attributeFormDefault" into account.
6784 */
6785 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006786 continue;
6787 } else {
6788 if (attributes->targetNamespace == NULL)
6789 continue;
6790 if (!xmlStrEqual(attributes->targetNamespace,
6791 attr->ns->href))
6792 continue;
6793 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006794 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006795 found = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006796 ctxt->cur = (xmlNodePtr) attributes;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006797
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006798 if (attributes->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006799 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
6800 "Internal error: attribute %s type not resolved\n",
6801 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006802 continue;
6803 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006804
6805 if (attributes->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
William M. Bracke7091952004-05-11 15:09:58 +00006806 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INVALIDATTR,
6807 "attribute %s on %s is prohibited\n",
6808 attributes->name, elem->name);
6809 /* Setting the state to XML_SCHEMAS_ATTR_CHECKED seems
6810 * not very logical but it suppresses the
6811 * "attribute is unknown" error report. Please change
6812 * this if you know better */
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006813 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6814 break;
6815 }
6816
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006817 value = xmlNodeListGetString(elem->doc, attr->children, 1);
6818 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6819 value);
6820 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006821 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
6822 XML_SCHEMAS_ERR_ATTRINVALID,
6823 "attribute %s on %s does not match type\n",
6824 attr->name, elem->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006825 } else {
6826 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6827 }
6828 if (value != NULL) {
6829 xmlFree(value);
6830 }
6831 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006832 if ((!found) && (attributes->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
William M. Bracke7091952004-05-11 15:09:58 +00006833 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_MISSING,
6834 "required attribute %s on %s is missing\n",
6835 attributes->name, elem->name);
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006836 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006837 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006838 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006839 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006840}
6841
6842/**
6843 * xmlSchemaValidateElement:
6844 * @ctxt: a schema validation context
6845 * @elem: an element
6846 *
6847 * Validate an element in a tree
6848 *
6849 * Returns 0 if the element is schemas valid, a positive error code
6850 * number otherwise and -1 in case of internal or API error.
6851 */
6852static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006853xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6854{
Daniel Veillard4255d502002-04-16 15:50:10 +00006855 xmlSchemaElementPtr elemDecl;
6856 int ret, attrBase;
6857
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006858 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006859 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6860 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006861 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006862 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6863 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006864 }
6865 /*
6866 * special case whe elementFormDefault is unqualified for top-level elem.
6867 */
William M. Bracke7091952004-05-11 15:09:58 +00006868 /*
6869 * This was removed, since elementFormDefault does not apply to top-level
6870 * element declarations.
6871 */
6872 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006873 if ((elemDecl == NULL) && (elem->ns != NULL) &&
6874 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6875 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6876 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6877 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6878 elem->name, NULL, NULL);
6879 }
William M. Bracke7091952004-05-11 15:09:58 +00006880 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006881
Daniel Veillard4255d502002-04-16 15:50:10 +00006882 /*
6883 * 3.3.4 : 1
6884 */
6885 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006886 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
6887 "Element %s not declared\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006888 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006889 }
6890 if (elemDecl->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006891 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
6892 "Element %s has no type\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006893 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006894 }
6895 /*
6896 * Verify the attributes
6897 */
6898 attrBase = ctxt->attrBase;
6899 ctxt->attrBase = ctxt->attrNr;
6900 xmlSchemaRegisterAttributes(ctxt, elem->properties);
6901 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6902 /*
6903 * Verify the element content recursively
6904 */
6905 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006906 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6907 (xmlRegExecCallbacks)
6908 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006909#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006910 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006911#endif
6912 }
6913 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006914 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006915 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006916#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006917 xmlGenericError(xmlGenericErrorContext,
6918 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006919#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006920 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006921 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
6922 "Element %s content check failed\n",
6923 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006924 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006925 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
6926 "Element %s content check failed\n",
6927 elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006928#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006929 } else {
6930 xmlGenericError(xmlGenericErrorContext,
6931 "Element %s content check succeeded\n",
6932 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006933
6934#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006935 }
6936 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006937 }
6938 /*
6939 * Verify that all attributes were Schemas-validated
6940 */
6941 xmlSchemaCheckAttributes(ctxt, elem);
6942 ctxt->attrNr = ctxt->attrBase;
6943 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006944
6945 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006946}
6947
6948/**
6949 * xmlSchemaValidateDocument:
6950 * @ctxt: a schema validation context
6951 * @doc: a parsed document tree
6952 *
6953 * Validate a document tree in memory.
6954 *
6955 * Returns 0 if the document is schemas valid, a positive error code
6956 * number otherwise and -1 in case of internal or API error.
6957 */
6958static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006959xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6960{
Daniel Veillard4255d502002-04-16 15:50:10 +00006961 xmlNodePtr root;
6962 xmlSchemaElementPtr elemDecl;
6963
6964 root = xmlDocGetRootElement(doc);
6965 if (root == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006966 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
6967 "document has no root\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006968 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006969 }
William M. Bracke7091952004-05-11 15:09:58 +00006970
Daniel Veillard4255d502002-04-16 15:50:10 +00006971 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006972 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6973 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006974 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006975 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6976 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006977 /*
6978 * special case whe elementFormDefault is unqualified for top-level elem.
6979 */
6980 if ((elemDecl == NULL) && (root->ns != NULL) &&
6981 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
6982 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6983 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6984 root->name, NULL, NULL);
6985 }
6986
Daniel Veillard4255d502002-04-16 15:50:10 +00006987 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006988 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
6989 "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006990 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006991 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
6992 "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006993 }
6994 /*
6995 * Okay, start the recursive validation
6996 */
6997 xmlSchemaValidateElement(ctxt, root);
6998
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006999 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00007000}
7001
7002/************************************************************************
7003 * *
7004 * SAX Validation code *
7005 * *
7006 ************************************************************************/
7007
7008/************************************************************************
7009 * *
7010 * Validation interfaces *
7011 * *
7012 ************************************************************************/
7013
7014/**
7015 * xmlSchemaNewValidCtxt:
7016 * @schema: a precompiled XML Schemas
7017 *
7018 * Create an XML Schemas validation context based on the given schema
7019 *
7020 * Returns the validation context or NULL in case of error
7021 */
7022xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007023xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
7024{
Daniel Veillard4255d502002-04-16 15:50:10 +00007025 xmlSchemaValidCtxtPtr ret;
7026
7027 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
7028 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007029 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007030 return (NULL);
7031 }
7032 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
7033 ret->schema = schema;
7034 ret->attrNr = 0;
7035 ret->attrMax = 10;
7036 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007037 sizeof
7038 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00007039 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007040 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
7041 free(ret);
7042 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007043 }
7044 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
7045 return (ret);
7046}
7047
7048/**
7049 * xmlSchemaFreeValidCtxt:
7050 * @ctxt: the schema validation context
7051 *
7052 * Free the resources associated to the schema validation context
7053 */
7054void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007055xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
7056{
Daniel Veillard4255d502002-04-16 15:50:10 +00007057 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007058 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007059 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007060 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00007061 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007062 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00007063 xmlFree(ctxt);
7064}
7065
7066/**
7067 * xmlSchemaSetValidErrors:
7068 * @ctxt: a schema validation context
7069 * @err: the error function
7070 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00007071 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00007072 *
7073 * Set the error and warning callback informations
7074 */
7075void
7076xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007077 xmlSchemaValidityErrorFunc err,
7078 xmlSchemaValidityWarningFunc warn, void *ctx)
7079{
Daniel Veillard4255d502002-04-16 15:50:10 +00007080 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007081 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007082 ctxt->error = err;
7083 ctxt->warning = warn;
7084 ctxt->userData = ctx;
7085}
7086
7087/**
7088 * xmlSchemaValidateDoc:
7089 * @ctxt: a schema validation context
7090 * @doc: a parsed document tree
7091 *
7092 * Validate a document tree in memory.
7093 *
7094 * Returns 0 if the document is schemas valid, a positive error code
7095 * number otherwise and -1 in case of internal or API error.
7096 */
7097int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007098xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
7099{
Daniel Veillard4255d502002-04-16 15:50:10 +00007100 int ret;
7101
7102 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007103 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007104
7105 ctxt->doc = doc;
7106 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007107 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007108}
7109
7110/**
7111 * xmlSchemaValidateStream:
7112 * @ctxt: a schema validation context
7113 * @input: the input to use for reading the data
7114 * @enc: an optional encoding information
7115 * @sax: a SAX handler for the resulting events
7116 * @user_data: the context to provide to the SAX handler.
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 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007123int
Daniel Veillard4255d502002-04-16 15:50:10 +00007124xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007125 xmlParserInputBufferPtr input, xmlCharEncoding enc,
7126 xmlSAXHandlerPtr sax, void *user_data)
7127{
Daniel Veillard4255d502002-04-16 15:50:10 +00007128 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007129 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007130 ctxt->input = input;
7131 ctxt->enc = enc;
7132 ctxt->sax = sax;
7133 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007134 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007135}
7136
7137#endif /* LIBXML_SCHEMAS_ENABLED */