blob: 27f584f317589d37af4de22208ec2740112cb4e6 [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
937/**
938 * xmlSchemaGetNamespace:
939 * @ctxt: the parser context
940 * @schema: the schemas containing the declaration
941 * @node: the node
942 * @qname: the QName to analyze
943 *
944 * Find the namespace name for the given declaration.
945 *
946 * Returns the local name for that declaration, as well as the namespace name
William M. Bracke7091952004-05-11 15:09:58 +0000947 * NOTE: This function is no longer used (Buchcik, May '04)
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000948 */
949static const xmlChar *
950xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
951 xmlNodePtr node, const xmlChar *qname,
952 const xmlChar **namespace) {
953 int len;
954 const xmlChar *name, *prefix, *def = NULL;
955 xmlNsPtr ns;
956
957 *namespace = NULL;
958
William M. Bracke7091952004-05-11 15:09:58 +0000959 /* TODO: The following seems to be not correct here:
960 * 1. The name of a declaration is a NCName, not a QName.
961 * 2. The attribute "targetNamespace" is allowed for the
962 * <schema> Element Information Item only.
963 * 3. One cannot evaluate the target namespace, by the type
964 * of declaration, since it is dependant on the xxxFormDefault
965 * of <schema> and the form attribute of an <element> or <attribute>.
966 */
967
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000968 if (xmlStrEqual(node->name, BAD_CAST "element") ||
969 xmlStrEqual(node->name, BAD_CAST "attribute") ||
970 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
971 xmlStrEqual(node->name, BAD_CAST "complexType")) {
972 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
973 }
974
William M. Bracke7091952004-05-11 15:09:58 +0000975
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000976 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
977 name = xmlSplitQName3(qname, &len);
978 if (name == NULL) {
979 if (def == NULL) {
980 if (xmlStrEqual(node->name, BAD_CAST "element")) {
981 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
982 *namespace = schema->targetNamespace;
983 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
984 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
985 *namespace = schema->targetNamespace;
986 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
987 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
988 *namespace = schema->targetNamespace;
989 }
990 } else {
991 *namespace = def;
992 }
993 return(qname);
994 }
William M. Bracke7091952004-05-11 15:09:58 +0000995
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000996 name = xmlDictLookup(ctxt->dict, name, -1);
997 prefix = xmlDictLookup(ctxt->dict, qname, len);
998 if (def != NULL) {
999 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
1000 "%s: presence of both prefix %s and targetNamespace\n",
1001 node->name, prefix);
1002 }
1003 ns = xmlSearchNs(node->doc, node, prefix);
1004 if (ns == NULL) {
1005 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1006 "%s: the QName prefix %s is undefined\n",
1007 node->name, prefix);
1008 return(name);
1009 }
1010 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1011 return(name);
1012}
1013
1014/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00001015 * *
1016 * Parsing functions *
1017 * *
1018 ************************************************************************/
1019
1020/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001021 * xmlSchemaGetElem:
1022 * @schema: the schemas context
1023 * @name: the element name
1024 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001025 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001026 *
1027 * Lookup a an element in the schemas or the accessible schemas
1028 *
1029 * Returns the element definition or NULL if not found.
1030 */
1031static xmlSchemaElementPtr
1032xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001033 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001034{
1035 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001036 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001037
1038 if ((name == NULL) || (schema == NULL))
1039 return (NULL);
1040
1041 if (namespace == NULL) {
1042 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001043 if ((ret != NULL) &&
1044 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001045 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001046 }
William M. Bracke7091952004-05-11 15:09:58 +00001047 /*
1048 * This one was removed, since top level element declarations have
1049 * the target namespace specified in targetNamespace of the <schema>
1050 * information element, even if elementFormDefault is "unqualified".
1051 */
1052
1053 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001054 if (xmlStrEqual(namespace, schema->targetNamespace))
1055 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1056 else
1057 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001058 if ((ret != NULL) &&
1059 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001060 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001061 }
William M. Bracke7091952004-05-11 15:09:58 +00001062 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001063 } else {
1064 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001065 if ((ret != NULL) &&
1066 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001067 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001068 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001069 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00001070 if (level > 0)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001071 import = xmlHashLookup(schema->schemasImports, namespace);
1072 if (import != NULL)
Daniel Veillardf2a12832003-11-24 13:04:35 +00001073 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001074#ifdef DEBUG
1075 if (ret == NULL) {
1076 if (namespace == NULL)
1077 fprintf(stderr, "Unable to lookup type %s", name);
1078 else
1079 fprintf(stderr, "Unable to lookup type %s:%s", name,
1080 namespace);
1081 }
1082#endif
1083 return (ret);
1084}
1085
1086/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001087 * xmlSchemaGetType:
1088 * @schema: the schemas context
1089 * @name: the type name
1090 * @ns: the type namespace
1091 *
1092 * Lookup a type in the schemas or the predefined types
1093 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001094 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001095 */
1096static xmlSchemaTypePtr
1097xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001098 const xmlChar * namespace)
1099{
Daniel Veillard4255d502002-04-16 15:50:10 +00001100 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001101 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001102
1103 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001104 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001105 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001106 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
1107 if (ret != NULL)
1108 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001109 }
1110 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001111 if (ret != NULL)
1112 return (ret);
1113 import = xmlHashLookup(schema->schemasImports, namespace);
1114 if (import != NULL)
1115 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001116#ifdef DEBUG
1117 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001118 if (namespace == NULL)
1119 fprintf(stderr, "Unable to lookup type %s", name);
1120 else
1121 fprintf(stderr, "Unable to lookup type %s:%s", name,
1122 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001123 }
1124#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001125 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001126}
1127
1128/************************************************************************
1129 * *
1130 * Parsing functions *
1131 * *
1132 ************************************************************************/
1133
1134#define IS_BLANK_NODE(n) \
1135 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1136
1137/**
1138 * xmlSchemaIsBlank:
1139 * @str: a string
1140 *
1141 * Check if a string is ignorable
1142 *
1143 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1144 */
1145static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001146xmlSchemaIsBlank(xmlChar * str)
1147{
Daniel Veillard4255d502002-04-16 15:50:10 +00001148 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001149 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001150 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001151 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001152 return (0);
1153 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001154 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001155 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001156}
1157
1158/**
1159 * xmlSchemaAddNotation:
1160 * @ctxt: a schema validation context
1161 * @schema: the schema being built
1162 * @name: the item name
1163 *
1164 * Add an XML schema Attrribute declaration
1165 * *WARNING* this interface is highly subject to change
1166 *
1167 * Returns the new struture or NULL in case of error
1168 */
1169static xmlSchemaNotationPtr
1170xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001171 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001172{
1173 xmlSchemaNotationPtr ret = NULL;
1174 int val;
1175
1176 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1177 return (NULL);
1178
1179 if (schema->notaDecl == NULL)
1180 schema->notaDecl = xmlHashCreate(10);
1181 if (schema->notaDecl == NULL)
1182 return (NULL);
1183
1184 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1185 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001186 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001187 return (NULL);
1188 }
1189 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001190 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001191 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1192 ret);
1193 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001194 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1195 XML_SCHEMAP_REDEFINED_NOTATION,
1196 "Notation %s already defined\n",
1197 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001198 xmlFree(ret);
1199 return (NULL);
1200 }
1201 return (ret);
1202}
1203
1204
1205/**
1206 * xmlSchemaAddAttribute:
1207 * @ctxt: a schema validation context
1208 * @schema: the schema being built
1209 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001210 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001211 *
1212 * Add an XML schema Attrribute declaration
1213 * *WARNING* this interface is highly subject to change
1214 *
1215 * Returns the new struture or NULL in case of error
1216 */
1217static xmlSchemaAttributePtr
1218xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001219 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001220{
1221 xmlSchemaAttributePtr ret = NULL;
1222 int val;
1223
1224 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1225 return (NULL);
1226
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001227#ifdef DEBUG
1228 fprintf(stderr, "Adding attribute %s\n", name);
1229 if (namespace != NULL)
1230 fprintf(stderr, " target namespace %s\n", namespace);
1231#endif
1232
Daniel Veillard4255d502002-04-16 15:50:10 +00001233 if (schema->attrDecl == NULL)
1234 schema->attrDecl = xmlHashCreate(10);
1235 if (schema->attrDecl == NULL)
1236 return (NULL);
1237
1238 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1239 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001240 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001241 return (NULL);
1242 }
1243 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001244 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1245 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001246 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001247 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001248 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001249 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1250 XML_SCHEMAP_REDEFINED_ATTR,
1251 "Attribute %s already defined\n",
1252 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001253 xmlFree(ret);
1254 return (NULL);
1255 }
1256 return (ret);
1257}
1258
1259/**
1260 * xmlSchemaAddAttributeGroup:
1261 * @ctxt: a schema validation context
1262 * @schema: the schema being built
1263 * @name: the item name
1264 *
1265 * Add an XML schema Attrribute Group declaration
1266 *
1267 * Returns the new struture or NULL in case of error
1268 */
1269static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001270xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1271 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001272{
1273 xmlSchemaAttributeGroupPtr ret = NULL;
1274 int val;
1275
1276 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1277 return (NULL);
1278
1279 if (schema->attrgrpDecl == NULL)
1280 schema->attrgrpDecl = xmlHashCreate(10);
1281 if (schema->attrgrpDecl == NULL)
1282 return (NULL);
1283
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001284 ret =
1285 (xmlSchemaAttributeGroupPtr)
1286 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001287 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001288 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001289 return (NULL);
1290 }
1291 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001292 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001293 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001294 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001295 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001296 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1297 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1298 "Attribute group %s already defined\n",
1299 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001300 xmlFree(ret);
1301 return (NULL);
1302 }
1303 return (ret);
1304}
1305
1306/**
1307 * xmlSchemaAddElement:
1308 * @ctxt: a schema validation context
1309 * @schema: the schema being built
1310 * @name: the type name
1311 * @namespace: the type namespace
1312 *
1313 * Add an XML schema Element declaration
1314 * *WARNING* this interface is highly subject to change
1315 *
1316 * Returns the new struture or NULL in case of error
1317 */
1318static xmlSchemaElementPtr
1319xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1320 const xmlChar * name, const xmlChar * namespace)
1321{
1322 xmlSchemaElementPtr ret = NULL;
1323 int val;
1324
1325 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1326 return (NULL);
1327
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001328#ifdef DEBUG
1329 fprintf(stderr, "Adding element %s\n", name);
1330 if (namespace != NULL)
1331 fprintf(stderr, " target namespace %s\n", namespace);
1332#endif
1333
Daniel Veillard4255d502002-04-16 15:50:10 +00001334 if (schema->elemDecl == NULL)
1335 schema->elemDecl = xmlHashCreate(10);
1336 if (schema->elemDecl == NULL)
1337 return (NULL);
1338
1339 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1340 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001341 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001342 return (NULL);
1343 }
1344 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001345 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1346 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001347 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001348 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001349 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001350 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001351
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001352 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001353 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1354 namespace, ret);
1355 if (val != 0) {
1356 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1357 XML_SCHEMAP_REDEFINED_ELEMENT,
1358 "Element %s already defined\n",
1359 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001360 xmlFree(ret);
1361 return (NULL);
1362 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001363 }
1364 return (ret);
1365}
1366
1367/**
1368 * xmlSchemaAddType:
1369 * @ctxt: a schema validation context
1370 * @schema: the schema being built
1371 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001372 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001373 *
1374 * Add an XML schema Simple Type definition
1375 * *WARNING* this interface is highly subject to change
1376 *
1377 * Returns the new struture or NULL in case of error
1378 */
1379static xmlSchemaTypePtr
1380xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001381 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001382{
1383 xmlSchemaTypePtr ret = NULL;
1384 int val;
1385
1386 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1387 return (NULL);
1388
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001389#ifdef DEBUG
1390 fprintf(stderr, "Adding type %s\n", name);
1391 if (namespace != NULL)
1392 fprintf(stderr, " target namespace %s\n", namespace);
1393#endif
1394
Daniel Veillard4255d502002-04-16 15:50:10 +00001395 if (schema->typeDecl == NULL)
1396 schema->typeDecl = xmlHashCreate(10);
1397 if (schema->typeDecl == NULL)
1398 return (NULL);
1399
1400 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1401 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001402 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001403 return (NULL);
1404 }
1405 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001406 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001407 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001408 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001409 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001410 if (ctxt->includes == 0) {
1411 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1412 XML_SCHEMAP_REDEFINED_TYPE,
1413 "Type %s already defined\n",
1414 name, NULL);
1415 xmlFree(ret);
1416 return (NULL);
1417 } else {
1418 xmlSchemaTypePtr prev;
1419
1420 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1421 if (prev == NULL) {
1422 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1423 XML_ERR_INTERNAL_ERROR,
1424 "Internal error on type %s definition\n",
1425 name, NULL);
1426 xmlFree(ret);
1427 return (NULL);
1428 }
1429 ret->redef = prev->redef;
1430 prev->redef = ret;
1431 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001432 }
1433 ret->minOccurs = 1;
1434 ret->maxOccurs = 1;
1435
1436 return (ret);
1437}
1438
1439/**
1440 * xmlSchemaAddGroup:
1441 * @ctxt: a schema validation context
1442 * @schema: the schema being built
1443 * @name: the group name
1444 *
1445 * Add an XML schema Group definition
1446 *
1447 * Returns the new struture or NULL in case of error
1448 */
1449static xmlSchemaTypePtr
1450xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001451 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001452{
1453 xmlSchemaTypePtr ret = NULL;
1454 int val;
1455
1456 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1457 return (NULL);
1458
1459 if (schema->groupDecl == NULL)
1460 schema->groupDecl = xmlHashCreate(10);
1461 if (schema->groupDecl == NULL)
1462 return (NULL);
1463
1464 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1465 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001466 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001467 return (NULL);
1468 }
1469 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001470 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001471 val =
1472 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1473 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001474 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001475 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1476 XML_SCHEMAP_REDEFINED_GROUP,
1477 "Group %s already defined\n",
1478 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001479 xmlFree(ret);
1480 return (NULL);
1481 }
1482 ret->minOccurs = 1;
1483 ret->maxOccurs = 1;
1484
1485 return (ret);
1486}
1487
1488/************************************************************************
1489 * *
1490 * Utilities for parsing *
1491 * *
1492 ************************************************************************/
1493
1494/**
1495 * xmlGetQNameProp:
1496 * @ctxt: a schema validation context
1497 * @node: a subtree containing XML Schema informations
1498 * @name: the attribute name
1499 * @namespace: the result namespace if any
1500 *
1501 * Extract a QName Attribute value
1502 *
1503 * Returns the NCName or NULL if not found, and also update @namespace
1504 * with the namespace URI
1505 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001506static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001507xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001508 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001509{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001510 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001511 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001512 const xmlChar *ret, *prefix;
1513 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001514
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001515 *namespace = NULL;
1516 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001517 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001518 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001519
Daniel Veillardba0153a2004-04-01 10:42:31 +00001520 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00001521 ns = xmlSearchNs(node->doc, node, 0);
1522 if (ns) {
1523 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1524 return (val);
1525 }
1526 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001527 ret = xmlSplitQName3(val, &len);
1528 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001529 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001530 }
1531 ret = xmlDictLookup(ctxt->dict, ret, -1);
1532 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001533
1534 ns = xmlSearchNs(node->doc, node, prefix);
1535 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001536 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1537 "Attribute %s: the QName prefix %s is undefined\n",
1538 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001539 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001540 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001541 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001542 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001543}
1544
1545/**
1546 * xmlGetMaxOccurs:
1547 * @ctxt: a schema validation context
1548 * @node: a subtree containing XML Schema informations
1549 *
1550 * Get the maxOccurs property
1551 *
1552 * Returns the default if not found, or the value
1553 */
1554static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001555xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1556{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001557 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001558 int ret = 0;
1559
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001560 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001561 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001562 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001563
1564 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001565 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001566 }
1567
1568 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001569 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001570 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001571 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001572 ret = ret * 10 + (*cur - '0');
1573 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001574 }
William M. Brack76e95df2003-10-18 16:20:14 +00001575 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001576 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001577 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001578 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1579 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001580 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001581 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001582 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001583}
1584
1585/**
1586 * xmlGetMinOccurs:
1587 * @ctxt: a schema validation context
1588 * @node: a subtree containing XML Schema informations
1589 *
1590 * Get the minOccurs property
1591 *
1592 * Returns the default if not found, or the value
1593 */
1594static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001595xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1596{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001597 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001598 int ret = 0;
1599
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001600 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001601 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001602 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001603
1604 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001605 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001606 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001607 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001608 ret = ret * 10 + (*cur - '0');
1609 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001610 }
William M. Brack76e95df2003-10-18 16:20:14 +00001611 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001612 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001613 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001614 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1615 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001616 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001617 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001618 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001619}
1620
1621/**
1622 * xmlGetBooleanProp:
1623 * @ctxt: a schema validation context
1624 * @node: a subtree containing XML Schema informations
1625 * @name: the attribute name
1626 * @def: the default value
1627 *
1628 * Get is a bolean property is set
1629 *
1630 * Returns the default if not found, 0 if found to be false,
1631 * 1 if found to be true
1632 */
1633static int
1634xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001635 const char *name, int def)
1636{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001637 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001638
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001639 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001640 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001641 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001642
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001643 if (xmlStrEqual(val, BAD_CAST "true"))
1644 def = 1;
1645 else if (xmlStrEqual(val, BAD_CAST "false"))
1646 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001647 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001648 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1649 "Attribute %s: the value %s is not boolean\n",
1650 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001651 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001652 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001653}
1654
1655/************************************************************************
1656 * *
1657 * Shema extraction from an Infoset *
1658 * *
1659 ************************************************************************/
1660static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1661 ctxt, xmlSchemaPtr schema,
1662 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001663static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1664 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001665 xmlSchemaPtr schema,
1666 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001667static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1668 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001669 xmlSchemaPtr schema,
1670 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001671 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001672static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1673 xmlSchemaPtr schema,
1674 xmlNodePtr node);
1675static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1676 xmlSchemaPtr schema,
1677 xmlNodePtr node);
1678static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1679 ctxt,
1680 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00001681 xmlNodePtr node,
1682 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00001683static xmlSchemaAttributeGroupPtr
1684xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1685 xmlSchemaPtr schema, xmlNodePtr node);
1686static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1687 xmlSchemaPtr schema,
1688 xmlNodePtr node);
1689static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1690 xmlSchemaPtr schema,
1691 xmlNodePtr node);
1692static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001693xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1694 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001695
1696/**
1697 * xmlSchemaParseAttrDecls:
1698 * @ctxt: a schema validation context
1699 * @schema: the schema being built
1700 * @node: a subtree containing XML Schema informations
1701 * @type: the hosting type
1702 *
1703 * parse a XML schema attrDecls declaration corresponding to
1704 * <!ENTITY % attrDecls
1705 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1706 */
1707static xmlNodePtr
1708xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1709 xmlNodePtr child, xmlSchemaTypePtr type)
1710{
1711 xmlSchemaAttributePtr lastattr, attr;
1712
1713 lastattr = NULL;
1714 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001715 (IS_SCHEMA(child, "attributeGroup"))) {
1716 attr = NULL;
1717 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00001718 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001719 } else if (IS_SCHEMA(child, "attributeGroup")) {
1720 attr = (xmlSchemaAttributePtr)
1721 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1722 }
1723 if (attr != NULL) {
1724 if (lastattr == NULL) {
1725 type->attributes = attr;
1726 lastattr = attr;
1727 } else {
1728 lastattr->next = attr;
1729 lastattr = attr;
1730 }
1731 }
1732 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001733 }
1734 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001735 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1736 if (attr != NULL) {
1737 if (lastattr == NULL) {
1738 type->attributes = attr;
1739 lastattr = attr;
1740 } else {
1741 lastattr->next = attr;
1742 lastattr = attr;
1743 }
1744 }
1745 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001746 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001747 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001748}
1749
1750/**
1751 * xmlSchemaParseAnnotation:
1752 * @ctxt: a schema validation context
1753 * @schema: the schema being built
1754 * @node: a subtree containing XML Schema informations
1755 *
1756 * parse a XML schema Attrribute declaration
1757 * *WARNING* this interface is highly subject to change
1758 *
William M. Bracke7091952004-05-11 15:09:58 +00001759 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00001760 * 1 in case of success.
1761 */
1762static xmlSchemaAnnotPtr
1763xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1764 xmlNodePtr node)
1765{
1766 xmlSchemaAnnotPtr ret;
1767
1768 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1769 return (NULL);
1770 ret = xmlSchemaNewAnnot(ctxt, node);
1771
1772 return (ret);
1773}
1774
1775/**
1776 * xmlSchemaParseFacet:
1777 * @ctxt: a schema validation context
1778 * @schema: the schema being built
1779 * @node: a subtree containing XML Schema informations
1780 *
1781 * parse a XML schema Facet declaration
1782 * *WARNING* this interface is highly subject to change
1783 *
1784 * Returns the new type structure or NULL in case of error
1785 */
1786static xmlSchemaFacetPtr
1787xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001788 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001789{
1790 xmlSchemaFacetPtr facet;
1791 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001792 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00001793
1794 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1795 return (NULL);
1796
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001797 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001798 if (facet == NULL) {
1799 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1800 return (NULL);
1801 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001802 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001803 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00001804 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001805 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1806 "Facet %s has no value\n", node->name, NULL);
1807 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001808 return (NULL);
1809 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001810 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001811 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001812 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001813 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001814 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001815 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001816 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001817 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001818 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001819 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001820 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001821 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001822 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001823 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001824 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001825 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001826 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001827 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001828 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001829 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001830 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001831 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1832 } else if (IS_SCHEMA(node, "minLength")) {
1833 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1834 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001835 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1836 "Unknown facet type %s\n", node->name, NULL);
1837 xmlSchemaFreeFacet(facet);
1838 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001839 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001840 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00001841 facet->value = value;
1842 child = node->children;
1843
1844 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001845 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1846 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001847 }
1848 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001849 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1850 "Facet %s has unexpected child content\n",
1851 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001852 }
1853 return (facet);
1854}
1855
1856/**
1857 * xmlSchemaParseAny:
1858 * @ctxt: a schema validation context
1859 * @schema: the schema being built
1860 * @node: a subtree containing XML Schema informations
1861 *
1862 * parse a XML schema Any declaration
1863 * *WARNING* this interface is highly subject to change
1864 *
1865 * Returns the new type structure or NULL in case of error
1866 */
1867static xmlSchemaTypePtr
1868xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1869 xmlNodePtr node)
1870{
1871 xmlSchemaTypePtr type;
1872 xmlNodePtr child = NULL;
1873 xmlChar name[30];
1874
1875 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1876 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001877 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001878 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001879 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001880 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001881 type->node = node;
1882 type->type = XML_SCHEMA_TYPE_ANY;
1883 child = node->children;
1884 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1885 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1886
1887 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001888 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1889 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001890 }
1891 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001892 xmlSchemaPErr2(ctxt, node, child,
1893 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1894 "Sequence %s has unexpected content\n", type->name,
1895 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001896 }
1897
1898 return (type);
1899}
1900
1901/**
1902 * xmlSchemaParseNotation:
1903 * @ctxt: a schema validation context
1904 * @schema: the schema being built
1905 * @node: a subtree containing XML Schema informations
1906 *
1907 * parse a XML schema Notation declaration
1908 *
1909 * Returns the new structure or NULL in case of error
1910 */
1911static xmlSchemaNotationPtr
1912xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001913 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001914{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001915 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00001916 xmlSchemaNotationPtr ret;
1917 xmlNodePtr child = NULL;
1918
1919 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1920 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001921 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001922 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001923 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1924 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001925 return (NULL);
1926 }
1927 ret = xmlSchemaAddNotation(ctxt, schema, name);
1928 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001929 return (NULL);
1930 }
1931 child = node->children;
1932 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001933 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1934 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001935 }
1936 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001937 xmlSchemaPErr2(ctxt, node, child,
1938 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1939 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001940 }
1941
1942 return (ret);
1943}
1944
1945/**
1946 * xmlSchemaParseAnyAttribute:
1947 * @ctxt: a schema validation context
1948 * @schema: the schema being built
1949 * @node: a subtree containing XML Schema informations
1950 *
1951 * parse a XML schema AnyAttrribute declaration
1952 * *WARNING* this interface is highly subject to change
1953 *
1954 * Returns an attribute def structure or NULL
1955 */
1956static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001957xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1958 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001959{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001960 const xmlChar *processContents;
Daniel Veillard4255d502002-04-16 15:50:10 +00001961 xmlSchemaAttributePtr ret;
1962 xmlNodePtr child = NULL;
1963 char name[100];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001964
Daniel Veillard4255d502002-04-16 15:50:10 +00001965
1966 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1967 return (NULL);
1968
1969 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
William M. Bracke7091952004-05-11 15:09:58 +00001970
1971 /* local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns); */
1972
1973 /*
1974 * TODO: namespace = ((##any | ##other) | List of (anyURI |
1975 * (##targetNamespace | * ##local)) ) : ##any
1976 */
1977 ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001978 if (ret == NULL) {
1979 return (NULL);
1980 }
William M. Bracke7091952004-05-11 15:09:58 +00001981 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001982 ret->id = xmlSchemaGetProp(ctxt, node, "id");
1983 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001984 if ((processContents == NULL)
1985 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1986 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1987 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1988 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1989 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1990 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001991 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001992 xmlSchemaPErr2(ctxt, node, child,
1993 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
William M. Bracke7091952004-05-11 15:09:58 +00001994 "anyAttribute has unexpected content "
1995 "for processContents: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001996 processContents, NULL);
1997 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001998 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001999
2000 child = node->children;
2001 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002002 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2003 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002004 }
2005 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002006 xmlSchemaPErr2(ctxt, node, child,
2007 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
2008 "anyAttribute %s has unexpected content\n",
2009 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002010 }
2011
2012 return (ret);
2013}
2014
2015
2016/**
2017 * xmlSchemaParseAttribute:
2018 * @ctxt: a schema validation context
2019 * @schema: the schema being built
2020 * @node: a subtree containing XML Schema informations
2021 *
2022 * parse a XML schema Attrribute declaration
2023 * *WARNING* this interface is highly subject to change
2024 *
William M. Bracke7091952004-05-11 15:09:58 +00002025 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002026 */
2027static xmlSchemaAttributePtr
2028xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002029 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002030{
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002031 const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal;
Daniel Veillard4255d502002-04-16 15:50:10 +00002032 xmlSchemaAttributePtr ret;
2033 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002034 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002035 int hasRefType = 0;
2036 int hasForm = 0;
2037
2038 /*
2039 * Note that the w3c spec assumes the schema to be validated with schema
2040 * for schemas beforehand.
2041 *
2042 * 3.2.3 Constraints on XML Representations of Attribute Declarations
2043 *
2044 * TODO: Complete implementation of:
2045 * 3.2.6 Schema Component Constraint: Attribute Declaration Properties
2046 * Correct
2047 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002048
2049 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2050 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002051
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002052 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002053 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002054 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002055 /* 3.2.3 : 3.1
2056 * One of ref or name must be present, but not both
2057 */
2058 if (ref == NULL) {
2059 xmlSchemaPErr(ctxt, node,
2060 XML_SCHEMAP_ATTR_NONAME_NOREF,
2061 "Attribute declaration has no \"name\" or \"ref\"\n",
2062 NULL, NULL);
2063 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002064 }
William M. Bracke7091952004-05-11 15:09:58 +00002065 hasRefType = 1;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002066 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2067 name = (const xmlChar *) buf;
2068 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002069 if (!topLevel) {
2070 /* 3.2.3 : 3.2
2071 * If ref is present, then all of <simpleType>,
2072 * form and type must be absent.
2073 */
2074 if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2075 xmlSchemaPErr(ctxt, node,
2076 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2077 "Attribute declaration %s has \"ref\", thus "
2078 "\"form\" must be absent\n", name, NULL);
2079 }
2080 if (xmlSchemaGetProp(ctxt, node, "type") != NULL) {
2081 xmlSchemaPErr(ctxt, node,
2082 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2083 "Attribute declaration %s has \"ref\", thus "
2084 "\"type\" must be absent\n", name, NULL);
2085 }
2086 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002087 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002088 const xmlChar *ns = NULL;
2089 /* 3.2.3 : 3.1
2090 * One of ref or name must be present, but not both
2091 */
2092 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2093 xmlSchemaPErr(ctxt, node,
2094 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2095 "Attribute declaration has both, \"name\" and "
2096 "\"ref\"\n", NULL, NULL);
2097 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002098
William M. Bracke7091952004-05-11 15:09:58 +00002099 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2100 /* Evaluate the target namespace */
2101 if (schema->targetNamespace != NULL) {
2102 if (topLevel) {
2103 ns = schema->targetNamespace;
2104 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2105 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2106 BAD_CAST "qualified")) {
2107 ns = schema->targetNamespace;
2108 }
2109 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2110 ns = schema->targetNamespace;
2111 }
2112 }
2113 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns);
2114
2115 /* 3.2.6 Schema Component Constraint: xmlns Not Allowed */
2116 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2117 xmlSchemaPErr(ctxt, node,
2118 XML_SCHEMAP_INVALID_ATTR_NAME,
2119 "The name of an attribute declaration must not match "
2120 "\"xmlns\".\n", NULL, NULL);
2121 }
2122
2123 /* 3.2.6 Schema Component Constraint: xsi: Not Allowed */
2124 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
2125 xmlSchemaPErr(ctxt, node,
2126 XML_SCHEMAP_INVALID_ATTR_NAME,
2127 "The target namespace of an attribute declaration, "
2128 "must not match \"http://www.w3.org/2001/"
2129 "XMLSchema-instance\"", NULL, NULL);
2130 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002131 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002132 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002133 return (NULL);
2134 }
William M. Bracke7091952004-05-11 15:09:58 +00002135 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
2136
2137 /* Handle the "use" attribute. */
2138 attrVal = xmlSchemaGetProp(ctxt, node, "use");
2139 if (attrVal != NULL) {
2140 if (xmlStrEqual(attrVal, BAD_CAST "optional"))
2141 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2142 else if (xmlStrEqual(attrVal, BAD_CAST "prohibited"))
2143 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
2144 else if (xmlStrEqual(attrVal, BAD_CAST "required"))
2145 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
2146 else
2147 xmlSchemaPErr(ctxt, node,
2148 XML_SCHEMAP_INVALID_ATTR_USE,
2149 "Attribute declaration %s has an invalid "
2150 "value for \"use\"\n", name, NULL);
2151 } else
2152 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002153
William M. Bracke7091952004-05-11 15:09:58 +00002154
2155 if (xmlSchemaGetProp(ctxt, node, "default") != NULL) {
2156 /* 3.2.3 : 1
2157 * default and fixed must not both be present.
2158 */
2159 if (xmlSchemaGetProp(ctxt, node, "fixed") != NULL) {
2160 xmlSchemaPErr(ctxt, node,
2161 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2162 "Attribute declaration has both, \"default\" "
2163 "and \"fixed\"\n", NULL, NULL);
2164 }
2165 /* 3.2.3 : 2
2166 * If default and use are both present, use must have
2167 * the actual value optional.
2168 */
2169 if (ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) {
2170 xmlSchemaPErr(ctxt, node,
2171 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2172 "Attribute declaration has \"default\" but "
2173 "\"use\" is not \"optional\"\n", NULL, NULL);
2174 }
2175 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002176
Daniel Veillard4255d502002-04-16 15:50:10 +00002177 ret->ref = ref;
2178 ret->refNs = refNs;
William M. Bracke7091952004-05-11 15:09:58 +00002179 /*
2180 * The setting of XML_SCHEMAS_ATTR_NSDEFAULT is not needed anymore,
2181 * since the target namespace was already evaluated and took
2182 * attributeFormDefault into account.
2183 */
2184 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002185 if ((ret->targetNamespace != NULL) &&
2186 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2187 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2188 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
William M. Bracke7091952004-05-11 15:09:58 +00002189 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002190 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
William M. Bracke7091952004-05-11 15:09:58 +00002191 if (ret->typeName != NULL)
2192 hasRefType = 1;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002193 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002194 child = node->children;
2195 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002196 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2197 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002198 }
2199 if (IS_SCHEMA(child, "simpleType")) {
William M. Bracke7091952004-05-11 15:09:58 +00002200 if (hasRefType) {
2201 /* 3.2.3 : 4
2202 * type and <simpleType> must not both be present.
2203 *
2204 * TODO: XML_SCHEMAP_INVALID_ATTR_COMBINATION seems not to be
2205 * a proper error type here.
2206 */
2207 xmlSchemaPErr2(ctxt, node, child,
2208 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2209 "Attribute declaration %s has both (\"ref\" or "
2210 "\"type\") and <simpleType>\n", name, NULL);
2211 } else
2212 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002213 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002214 }
2215 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002216 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2217 "attribute %s has unexpected content\n", name,
2218 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002219 }
2220
2221 return (ret);
2222}
2223
2224/**
2225 * xmlSchemaParseAttributeGroup:
2226 * @ctxt: a schema validation context
2227 * @schema: the schema being built
2228 * @node: a subtree containing XML Schema informations
2229 *
2230 * parse a XML schema Attribute Group declaration
2231 * *WARNING* this interface is highly subject to change
2232 *
2233 * Returns the attribute group or NULL in case of error.
2234 */
2235static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002236xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
2237 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002238{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002239 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002240 xmlSchemaAttributeGroupPtr ret;
2241 xmlSchemaAttributePtr last = NULL, attr;
2242 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002243 const xmlChar *oldcontainer;
2244 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002245
2246 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2247 return (NULL);
2248 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002249 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002250 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002251
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002252 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2253 if (ref == NULL) {
2254 xmlSchemaPErr2(ctxt, node, child,
2255 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2256 "AttributeGroup has no name nor ref\n", NULL,
2257 NULL);
2258 return (NULL);
2259 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002260 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2261 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002262 if (name == NULL) {
2263 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2264 return (NULL);
2265 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002266 }
2267 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2268 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002269 return (NULL);
2270 }
2271 ret->ref = ref;
2272 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002273 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002274 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002275 child = node->children;
2276 ctxt->container = name;
2277 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002278 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2279 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002280 }
2281 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002282 (IS_SCHEMA(child, "attributeGroup"))) {
2283 attr = NULL;
2284 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00002285 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002286 } else if (IS_SCHEMA(child, "attributeGroup")) {
2287 attr = (xmlSchemaAttributePtr)
2288 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2289 }
2290 if (attr != NULL) {
2291 if (last == NULL) {
2292 ret->attributes = attr;
2293 last = attr;
2294 } else {
2295 last->next = attr;
2296 last = attr;
2297 }
2298 }
2299 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002300 }
2301 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002302 TODO
2303 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002304 }
2305 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002306 xmlSchemaPErr2(ctxt, node, child,
2307 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2308 "attribute group %s has unexpected content\n", name,
2309 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002310 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002311 ctxt->container = oldcontainer;
2312 return (ret);
2313}
2314
2315/**
2316 * xmlSchemaParseElement:
2317 * @ctxt: a schema validation context
2318 * @schema: the schema being built
2319 * @node: a subtree containing XML Schema informations
2320 *
2321 * parse a XML schema Element declaration
2322 * *WARNING* this interface is highly subject to change
2323 *
William M. Bracke7091952004-05-11 15:09:58 +00002324 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002325 */
2326static xmlSchemaElementPtr
2327xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2328 xmlNodePtr node, int toplevel)
2329{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002330 const xmlChar *name, *fixed;
2331 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002332 xmlSchemaElementPtr ret;
2333 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002334 const xmlChar *oldcontainer;
2335 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002336 xmlAttrPtr attr;
2337
2338 /* 3.3.3 Constraints on XML Representations of Element Declarations */
2339 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002340
2341 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2342 return (NULL);
2343 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002344 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002345 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002346
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002347 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002348 /* 3.3.3 : 2.1
2349 * One of ref or name must be present, but not both
2350 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002351 if (ref == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00002352 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002353 XML_SCHEMAP_ELEM_NONAME_NOREF,
2354 "Element has no name nor ref\n", NULL, NULL);
2355 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002356 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002357 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2358 name = (const xmlChar *) buf;
2359 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2360 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002361 const xmlChar *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002362
William M. Bracke7091952004-05-11 15:09:58 +00002363 /* Evaluate the target namespace */
2364 if (schema->targetNamespace != NULL) {
2365 if (toplevel) {
2366 ns = schema->targetNamespace;
2367 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2368 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2369 BAD_CAST "qualified")) {
2370 ns = schema->targetNamespace;
2371 }
2372 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2373 ns = schema->targetNamespace;
2374 }
2375 }
2376 /*local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2377 ret = xmlSchemaAddElement(ctxt, schema, name, ns);
2378 /* 3.3.3 : 2.1
2379 * One of ref or name must be present, but not both
2380 */
2381 if ((!toplevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2382 xmlSchemaPErr(ctxt, node,
2383 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2384 "Element declaration has both, \"name\" and "
2385 "\"ref\"\n", NULL, NULL);
2386 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002387 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002388 if (ret != NULL)
2389 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002390 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002391 return (NULL);
2392 }
2393 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2394 ret->ref = ref;
2395 ret->refNs = refNs;
2396 if (ref != NULL)
2397 ret->flags |= XML_SCHEMAS_ELEM_REF;
William M. Bracke7091952004-05-11 15:09:58 +00002398
2399 /* 3.3.3 : 2.2 */
2400 if ((!toplevel) && (ref != NULL)) {
2401 attr = node->properties;
2402 while (attr != NULL) {
2403 if ((attr->ns == NULL) &&
2404 (!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
2405 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
2406 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
2407 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
2408
2409 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2410 "Element declaration %s: only minOccurs, maxOccurs "
2411 "and id are allowed in addition to ref\n",
2412 ret->name, NULL);
2413 }
2414 attr = attr->next;
2415 }
2416 }
2417
Daniel Veillard4255d502002-04-16 15:50:10 +00002418 if (toplevel)
2419 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2420 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2421 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2422 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2423 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2424 ctxt->container = name;
2425
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002426 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002427 ret->namedType =
William M. Bracke7091952004-05-11 15:09:58 +00002428 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002429 ret->substGroup =
2430 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2431 &(ret->substGroupNs));
William M. Bracke7091952004-05-11 15:09:58 +00002432 if ((ret->substGroup != NULL) && (!toplevel)) {
2433 /* 3.3.6 : 3 */
2434 /*
2435 * TODO: This seems to be redundant, since the schema for schemas
2436 * already prohibits the use of the "substitutionGroup" attribute
2437 * in local element declarations.
2438 */
2439 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2440 "Element declaration %s: substitutionGroup is allowed "
2441 "on top-level declarations only\n", ret->name, NULL);
2442
2443 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002444 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002445 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2446 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002447
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002448 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002449 if ((ret->value != NULL) && (fixed != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00002450 /* 3.3.3 : 1
2451 * default and fixed must not both be present.
2452 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002453 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2454 "Element %s has both default and fixed\n",
2455 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002456 } else if (fixed != NULL) {
2457 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002458 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002459 }
2460
2461 child = node->children;
2462 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002463 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2464 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002465 }
William M. Bracke7091952004-05-11 15:09:58 +00002466 if (ref != NULL) {
2467 /* 3.3.3 (2.2) */
2468 while (child != NULL) {
2469 if ((IS_SCHEMA(child, "complexType")) ||
2470 (IS_SCHEMA(child, "simpleType")) ||
2471 (IS_SCHEMA(child, "unique")) ||
2472 (IS_SCHEMA(child, "key")) ||
2473 (IS_SCHEMA(child, "keyref"))) {
2474
2475 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_REF_AND_CONTENT,
2476 "Element declaration %s: only annotation is "
2477 "allowed as content in addition to ref\n",
2478 ret->name, NULL);
2479 } else {
2480 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2481 "element %s has unexpected content\n", name, NULL);
2482 }
2483 child = child->next;
2484 }
2485 } else {
2486 if (IS_SCHEMA(child, "complexType")) {
2487 /* 3.3.3 : 3
2488 * type and either <simpleType> or <complexType> are mutually
2489 * exclusive
2490 */
2491 if (ret->namedType != NULL) {
2492 xmlSchemaPErr2(ctxt, node, child,
2493 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2494 "Element declaration %s has both \"type\" "
2495 "and a local complex type\n",
2496 ret->name, NULL);
2497 } else
2498 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
2499 child = child->next;
2500 } else if (IS_SCHEMA(child, "simpleType")) {
2501 /* 3.3.3 : 3
2502 * type and either <simpleType> or <complexType> are
2503 * mutually exclusive
2504 */
2505 if (ret->namedType != NULL) {
2506 xmlSchemaPErr2(ctxt, node, child,
2507 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2508 "Element declaration %s has both \"type\" "
2509 "and a local simple type\n",
2510 ret->name, NULL);
2511 } else
2512 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2513 child = child->next;
2514 }
2515
2516 while ((IS_SCHEMA(child, "unique")) ||
2517 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2518 TODO child = child->next;
2519 }
2520 if (child != NULL) {
2521 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2522 "element %s has unexpected content\n", name, NULL);
2523 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002524 }
2525
2526 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002527 return (ret);
2528}
2529
2530/**
2531 * xmlSchemaParseUnion:
2532 * @ctxt: a schema validation context
2533 * @schema: the schema being built
2534 * @node: a subtree containing XML Schema informations
2535 *
2536 * parse a XML schema Union definition
2537 * *WARNING* this interface is highly subject to change
2538 *
William M. Bracke7091952004-05-11 15:09:58 +00002539 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002540 * 1 in case of success.
2541 */
2542static xmlSchemaTypePtr
2543xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002544 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002545{
2546 xmlSchemaTypePtr type, subtype, last = NULL;
2547 xmlNodePtr child = NULL;
2548 xmlChar name[30];
2549
2550 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2551 return (NULL);
2552
2553
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002554 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002555 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002556 if (type == NULL)
2557 return (NULL);
2558 type->node = node;
Daniel Veillard377e1a92004-04-16 16:30:05 +00002559 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002560 type->id = xmlSchemaGetProp(ctxt, node, "id");
2561 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002562
2563 child = node->children;
2564 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002565 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2566 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002567 }
2568 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002569 subtype = (xmlSchemaTypePtr)
2570 xmlSchemaParseSimpleType(ctxt, schema, child);
2571 if (subtype != NULL) {
2572 if (last == NULL) {
2573 type->subtypes = subtype;
2574 last = subtype;
2575 } else {
2576 last->next = subtype;
2577 last = subtype;
2578 }
2579 last->next = NULL;
2580 }
2581 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002582 }
2583 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002584 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2585 "Union %s has unexpected content\n", type->name,
2586 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002587 }
2588 return (type);
2589}
2590
2591/**
2592 * xmlSchemaParseList:
2593 * @ctxt: a schema validation context
2594 * @schema: the schema being built
2595 * @node: a subtree containing XML Schema informations
2596 *
2597 * parse a XML schema List definition
2598 * *WARNING* this interface is highly subject to change
2599 *
William M. Bracke7091952004-05-11 15:09:58 +00002600 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002601 * 1 in case of success.
2602 */
2603static xmlSchemaTypePtr
2604xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002605 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002606{
2607 xmlSchemaTypePtr type, subtype;
2608 xmlNodePtr child = NULL;
2609 xmlChar name[30];
2610
2611 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2612 return (NULL);
2613
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002614 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002615 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002616 if (type == NULL)
2617 return (NULL);
2618 type->node = node;
2619 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002620 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002621 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2622
2623 child = node->children;
2624 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002625 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2626 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002627 }
William M. Bracke7091952004-05-11 15:09:58 +00002628
Daniel Veillard4255d502002-04-16 15:50:10 +00002629 subtype = NULL;
2630 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002631 subtype = (xmlSchemaTypePtr)
2632 xmlSchemaParseSimpleType(ctxt, schema, child);
2633 child = child->next;
2634 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002635 }
2636 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002637 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2638 "List %s has unexpected content\n", type->name,
2639 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002640 }
2641 return (type);
2642}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002643
Daniel Veillard4255d502002-04-16 15:50:10 +00002644/**
2645 * xmlSchemaParseSimpleType:
2646 * @ctxt: a schema validation context
2647 * @schema: the schema being built
2648 * @node: a subtree containing XML Schema informations
2649 *
2650 * parse a XML schema Simple Type definition
2651 * *WARNING* this interface is highly subject to change
2652 *
William M. Bracke7091952004-05-11 15:09:58 +00002653 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002654 * 1 in case of success.
2655 */
2656static xmlSchemaTypePtr
2657xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2658 xmlNodePtr node)
2659{
2660 xmlSchemaTypePtr type, subtype;
2661 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002662 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002663
2664 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2665 return (NULL);
2666
2667
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002668 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002669 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002670 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002671
William M. Bracke7091952004-05-11 15:09:58 +00002672 snprintf(buf, 99, "simpleType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002673 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002674 } else {
2675 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2676 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002677 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002678 if (type == NULL)
2679 return (NULL);
2680 type->node = node;
2681 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002682 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002683
2684 child = node->children;
2685 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002686 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2687 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002688 }
2689 subtype = NULL;
2690 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002691 subtype = (xmlSchemaTypePtr)
2692 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2693 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002694 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002695 subtype = (xmlSchemaTypePtr)
2696 xmlSchemaParseList(ctxt, schema, child);
2697 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002698 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002699 subtype = (xmlSchemaTypePtr)
2700 xmlSchemaParseUnion(ctxt, schema, child);
2701 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002702 }
2703 type->subtypes = subtype;
William M. Bracke7091952004-05-11 15:09:58 +00002704 if (subtype == NULL) {
2705 xmlSchemaPErr2(ctxt, node, child,
2706 XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD,
2707 "SimpleType %s does not define a variety\n",
2708 type->name, NULL);
2709 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002710 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002711 xmlSchemaPErr2(ctxt, node, child,
2712 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2713 "SimpleType %s has unexpected content\n",
2714 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002715 }
2716
2717 return (type);
2718}
2719
2720
2721/**
2722 * xmlSchemaParseGroup:
2723 * @ctxt: a schema validation context
2724 * @schema: the schema being built
2725 * @node: a subtree containing XML Schema informations
2726 *
2727 * parse a XML schema Group definition
2728 * *WARNING* this interface is highly subject to change
2729 *
William M. Bracke7091952004-05-11 15:09:58 +00002730 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002731 * 1 in case of success.
2732 */
2733static xmlSchemaTypePtr
2734xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002735 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002736{
2737 xmlSchemaTypePtr type, subtype;
2738 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002739 const xmlChar *name;
2740 const xmlChar *ref = NULL, *refNs = NULL;
2741 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002742
2743 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2744 return (NULL);
2745
2746
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002747 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002748 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002749
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002750 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2751 if (ref == NULL) {
2752 xmlSchemaPErr2(ctxt, node, child,
2753 XML_SCHEMAP_GROUP_NONAME_NOREF,
2754 "Group has no name nor ref\n", NULL, NULL);
2755 return (NULL);
2756 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002757 if (refNs == NULL)
2758 refNs = schema->targetNamespace;
2759 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2760 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00002761 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002762 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002763 if (type == NULL)
2764 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00002765
Daniel Veillard4255d502002-04-16 15:50:10 +00002766 type->node = node;
2767 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002768 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002769 type->ref = ref;
2770 type->refNs = refNs;
2771 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2772 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2773
2774 child = node->children;
2775 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002776 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2777 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002778 }
2779 subtype = NULL;
2780 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002781 subtype = (xmlSchemaTypePtr)
2782 xmlSchemaParseAll(ctxt, schema, child);
2783 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002784 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002785 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2786 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002787 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002788 subtype = (xmlSchemaTypePtr)
2789 xmlSchemaParseSequence(ctxt, schema, child);
2790 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002791 }
2792 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002793 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002794 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002795 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2796 "Group %s has unexpected content\n", type->name,
2797 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002798 }
2799
2800 return (type);
2801}
2802
2803/**
2804 * xmlSchemaParseAll:
2805 * @ctxt: a schema validation context
2806 * @schema: the schema being built
2807 * @node: a subtree containing XML Schema informations
2808 *
2809 * parse a XML schema All definition
2810 * *WARNING* this interface is highly subject to change
2811 *
William M. Bracke7091952004-05-11 15:09:58 +00002812 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002813 * 1 in case of success.
2814 */
2815static xmlSchemaTypePtr
2816xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002817 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002818{
2819 xmlSchemaTypePtr type, subtype, last = NULL;
2820 xmlNodePtr child = NULL;
2821 xmlChar name[30];
2822
2823 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2824 return (NULL);
2825
2826
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002827 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002828 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002829 if (type == NULL)
2830 return (NULL);
2831 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002832 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002833 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002834 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002835 if (type->minOccurs > 1)
2836 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2837 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002838 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002839 if (type->maxOccurs > 1)
2840 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2841 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002842
2843 child = node->children;
2844 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002845 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2846 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002847 }
2848 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002849 subtype = (xmlSchemaTypePtr)
2850 xmlSchemaParseElement(ctxt, schema, child, 0);
2851 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00002852 if (subtype->minOccurs > 1)
2853 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
2854 "invalid value for minOccurs (must be 0 or 1)\n",
2855 NULL, NULL);
2856 if (subtype->maxOccurs > 1)
2857 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
2858 "invalid value for maxOccurs (must be 0 or 1)\n",
2859 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002860 if (last == NULL) {
2861 type->subtypes = subtype;
2862 last = subtype;
2863 } else {
2864 last->next = subtype;
2865 last = subtype;
2866 }
2867 last->next = NULL;
2868 }
2869 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002870 }
2871 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002872 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2873 "All %s has unexpected content\n", type->name,
2874 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002875 }
2876
2877 return (type);
2878}
2879
2880/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002881 * xmlSchemaImportSchema
2882 *
2883 * @ctxt: a schema validation context
2884 * @schemaLocation: an URI defining where to find the imported schema
2885 *
2886 * import a XML schema
2887 * *WARNING* this interface is highly subject to change
2888 *
2889 * Returns -1 in case of error and 1 in case of success.
2890 */
2891static xmlSchemaImportPtr
2892xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2893 const xmlChar *schemaLocation)
2894{
2895 xmlSchemaImportPtr import;
2896 xmlSchemaParserCtxtPtr newctxt;
2897
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002898 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00002899 if (newctxt == NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002900 xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00002901 NULL);
2902 return (NULL);
2903 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002904 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
2905 /* Keep the same dictionnary for parsing, really */
2906 xmlDictReference(ctxt->dict);
2907 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002908 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002909 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
2910
Daniel Veillard1d913862003-11-21 00:28:39 +00002911 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2912 ctxt->userData);
2913
2914 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2915 if (import == NULL) {
2916 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2917 NULL);
2918 xmlSchemaFreeParserCtxt(newctxt);
2919 return (NULL);
2920 }
2921
2922 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002923 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00002924 import->schema = xmlSchemaParse(newctxt);
2925
2926 if (import->schema == NULL) {
2927 /* FIXME use another error enum here ? */
2928 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2929 "failed to import schema at location %s\n",
2930 schemaLocation, NULL);
2931
2932 xmlSchemaFreeParserCtxt(newctxt);
2933 if (import->schemaLocation != NULL)
2934 xmlFree((xmlChar *)import->schemaLocation);
2935 xmlFree(import);
2936 return NULL;
2937 }
2938
2939 xmlSchemaFreeParserCtxt(newctxt);
2940 return import;
2941}
2942
2943
2944/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002945 * xmlSchemaParseImport:
2946 * @ctxt: a schema validation context
2947 * @schema: the schema being built
2948 * @node: a subtree containing XML Schema informations
2949 *
2950 * parse a XML schema Import definition
2951 * *WARNING* this interface is highly subject to change
2952 *
William M. Bracke7091952004-05-11 15:09:58 +00002953 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard5a872412002-05-22 06:40:27 +00002954 * 1 in case of success.
2955 */
2956static int
2957xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002958 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002959{
2960 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00002961 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002962 const xmlChar *namespace;
2963 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00002964 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00002965 xmlURIPtr check;
2966
Daniel Veillard1d913862003-11-21 00:28:39 +00002967
Daniel Veillard5a872412002-05-22 06:40:27 +00002968 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2969 return (-1);
2970
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002971 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00002972 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002973 check = xmlParseURI((const char *) namespace);
2974 if (check == NULL) {
2975 xmlSchemaPErr2(ctxt, node, child,
2976 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2977 "Import namespace attribute is not an URI: %s\n",
2978 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002979 return (-1);
2980 } else {
2981 xmlFreeURI(check);
2982 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002983 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002984 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00002985 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002986 xmlChar *base = NULL;
2987 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002988 check = xmlParseURI((const char *) schemaLocation);
2989 if (check == NULL) {
2990 xmlSchemaPErr2(ctxt, node, child,
2991 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2992 "Import schemaLocation attribute is not an URI: %s\n",
2993 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002994 return (-1);
2995 } else {
2996 xmlFreeURI(check);
2997 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002998 base = xmlNodeGetBase(node->doc, node);
2999 if (base == NULL) {
3000 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3001 } else {
3002 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003003 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00003004 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003005 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003006 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3007 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00003008 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003009 }
3010 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003011 schema->schemasImports = xmlHashCreate(10);
3012 if (schema->schemasImports == NULL) {
3013 xmlSchemaPErr2(ctxt, node, child,
3014 XML_SCHEMAP_FAILED_BUILD_IMPORT,
3015 "Internal: failed to build import table\n",
3016 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003017 return (-1);
3018 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003019 }
3020 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003021 import = xmlHashLookup(schema->schemasImports,
3022 XML_SCHEMAS_DEFAULT_NAMESPACE);
3023 if (import != NULL)
3024 previous = import->schemaLocation;
3025 else
3026 previous = NULL;
3027
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003028 if (schemaLocation != NULL) {
3029 if (previous != NULL) {
3030 if (!xmlStrEqual(schemaLocation, previous)) {
3031 xmlSchemaPErr2(ctxt, node, child,
3032 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003033 "Redefining import for default namespace "
3034 "with a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003035 schemaLocation, NULL);
3036 }
3037 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003038 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3039 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003040 return (-1);
3041 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003042 xmlHashAddEntry(schema->schemasImports,
3043 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00003044 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003045 }
3046 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003047 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003048 import = xmlHashLookup(schema->schemasImports, namespace);
3049 if (import != NULL)
3050 previous = import->schemaLocation;
3051 else
3052 previous = NULL;
3053
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003054 if (schemaLocation != NULL) {
3055 if (previous != NULL) {
3056 if (!xmlStrEqual(schemaLocation, previous)) {
3057 xmlSchemaPErr2(ctxt, node, child,
3058 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003059 "Redefining import for namespace %s with "
3060 "a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003061 namespace, schemaLocation);
3062 }
3063 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003064 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3065 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003066 return (-1);
3067 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003068 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00003069 namespace, import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003070 }
3071 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003072 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003073
3074 child = node->children;
3075 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003076 /*
3077 * the annotations here are simply discarded ...
3078 */
3079 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00003080 }
3081 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003082 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
3083 "Import has unexpected content\n", NULL, NULL);
3084 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003085 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003086 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003087}
3088
3089/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003090 * xmlSchemaCleanupDoc:
3091 * @ctxt: a schema validation context
3092 * @node: the root of the document.
3093 *
3094 * removes unwanted nodes in a schemas document tree
3095 */
3096static void
3097xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
3098{
3099 xmlNodePtr delete, cur;
3100
3101 if ((ctxt == NULL) || (root == NULL)) return;
3102
3103 /*
3104 * Remove all the blank text nodes
3105 */
3106 delete = NULL;
3107 cur = root;
3108 while (cur != NULL) {
3109 if (delete != NULL) {
3110 xmlUnlinkNode(delete);
3111 xmlFreeNode(delete);
3112 delete = NULL;
3113 }
3114 if (cur->type == XML_TEXT_NODE) {
3115 if (IS_BLANK_NODE(cur)) {
3116 if (xmlNodeGetSpacePreserve(cur) != 1) {
3117 delete = cur;
3118 }
3119 }
3120 } else if ((cur->type != XML_ELEMENT_NODE) &&
3121 (cur->type != XML_CDATA_SECTION_NODE)) {
3122 delete = cur;
3123 goto skip_children;
3124 }
3125
3126 /*
3127 * Skip to next node
3128 */
3129 if (cur->children != NULL) {
3130 if ((cur->children->type != XML_ENTITY_DECL) &&
3131 (cur->children->type != XML_ENTITY_REF_NODE) &&
3132 (cur->children->type != XML_ENTITY_NODE)) {
3133 cur = cur->children;
3134 continue;
3135 }
3136 }
3137 skip_children:
3138 if (cur->next != NULL) {
3139 cur = cur->next;
3140 continue;
3141 }
3142
3143 do {
3144 cur = cur->parent;
3145 if (cur == NULL)
3146 break;
3147 if (cur == root) {
3148 cur = NULL;
3149 break;
3150 }
3151 if (cur->next != NULL) {
3152 cur = cur->next;
3153 break;
3154 }
3155 } while (cur != NULL);
3156 }
3157 if (delete != NULL) {
3158 xmlUnlinkNode(delete);
3159 xmlFreeNode(delete);
3160 delete = NULL;
3161 }
3162}
3163
3164/**
3165 * xmlSchemaParseSchemaTopLevel:
3166 * @ctxt: a schema validation context
3167 * @schema: the schemas
3168 * @nodes: the list of top level nodes
3169 *
3170 * Returns the internal XML Schema structure built from the resource or
3171 * NULL in case of error
3172 */
3173static void
3174xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
3175 xmlSchemaPtr schema, xmlNodePtr nodes)
3176{
3177 xmlNodePtr child;
3178 xmlSchemaAnnotPtr annot;
3179
3180 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
3181 return;
3182
3183 child = nodes;
3184 while ((IS_SCHEMA(child, "include")) ||
3185 (IS_SCHEMA(child, "import")) ||
3186 (IS_SCHEMA(child, "redefine")) ||
3187 (IS_SCHEMA(child, "annotation"))) {
3188 if (IS_SCHEMA(child, "annotation")) {
3189 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3190 if (schema->annot == NULL)
3191 schema->annot = annot;
3192 else
3193 xmlSchemaFreeAnnot(annot);
3194 } else if (IS_SCHEMA(child, "import")) {
3195 xmlSchemaParseImport(ctxt, schema, child);
3196 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003197 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003198 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003199 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003200 } else if (IS_SCHEMA(child, "redefine")) {
3201 TODO
3202 }
3203 child = child->next;
3204 }
3205 while (child != NULL) {
3206 if (IS_SCHEMA(child, "complexType")) {
3207 xmlSchemaParseComplexType(ctxt, schema, child);
3208 child = child->next;
3209 } else if (IS_SCHEMA(child, "simpleType")) {
3210 xmlSchemaParseSimpleType(ctxt, schema, child);
3211 child = child->next;
3212 } else if (IS_SCHEMA(child, "element")) {
3213 xmlSchemaParseElement(ctxt, schema, child, 1);
3214 child = child->next;
3215 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003216 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003217 child = child->next;
3218 } else if (IS_SCHEMA(child, "attributeGroup")) {
3219 xmlSchemaParseAttributeGroup(ctxt, schema, child);
3220 child = child->next;
3221 } else if (IS_SCHEMA(child, "group")) {
3222 xmlSchemaParseGroup(ctxt, schema, child);
3223 child = child->next;
3224 } else if (IS_SCHEMA(child, "notation")) {
3225 xmlSchemaParseNotation(ctxt, schema, child);
3226 child = child->next;
3227 } else {
3228 xmlSchemaPErr2(ctxt, NULL, child,
3229 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3230 "Schemas: unexpected element %s here \n",
3231 child->name, NULL);
3232 child = child->next;
3233 }
3234 while (IS_SCHEMA(child, "annotation")) {
3235 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3236 if (schema->annot == NULL)
3237 schema->annot = annot;
3238 else
3239 xmlSchemaFreeAnnot(annot);
3240 child = child->next;
3241 }
3242 }
3243}
3244
3245/**
3246 * xmlSchemaParseInclude:
3247 * @ctxt: a schema validation context
3248 * @schema: the schema being built
3249 * @node: a subtree containing XML Schema informations
3250 *
3251 * parse a XML schema Include definition
3252 *
William M. Bracke7091952004-05-11 15:09:58 +00003253 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003254 * 1 in case of success.
3255 */
3256static int
3257xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3258 xmlNodePtr node)
3259{
3260 xmlNodePtr child = NULL;
3261 const xmlChar *schemaLocation;
3262 xmlURIPtr check;
3263 xmlDocPtr doc;
3264 xmlNodePtr root;
3265 xmlSchemaIncludePtr include;
3266
3267
3268 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3269 return (-1);
3270
3271 /*
3272 * Preliminary step, extract the URI-Reference for the include and
3273 * make an URI from the base.
3274 */
3275 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
3276 if (schemaLocation != NULL) {
3277 xmlChar *base = NULL;
3278 xmlChar *URI = NULL;
3279 check = xmlParseURI((const char *) schemaLocation);
3280 if (check == NULL) {
3281 xmlSchemaPErr2(ctxt, node, child,
3282 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3283 "Include schemaLocation attribute is not an URI: %s\n",
3284 schemaLocation, NULL);
3285 return (-1);
3286 } else {
3287 xmlFreeURI(check);
3288 }
3289 base = xmlNodeGetBase(node->doc, node);
3290 if (base == NULL) {
3291 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3292 } else {
3293 URI = xmlBuildURI(schemaLocation, base);
3294 xmlFree(base);
3295 }
3296 if (URI != NULL) {
3297 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3298 xmlFree(URI);
3299 }
3300 } else {
3301 xmlSchemaPErr2(ctxt, node, child,
3302 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3303 "Include schemaLocation attribute missing\n",
3304 NULL, NULL);
3305 return (-1);
3306 }
3307
3308 child = node->children;
3309 while (IS_SCHEMA(child, "annotation")) {
3310 /*
3311 * the annotations here are simply discarded ...
3312 */
3313 child = child->next;
3314 }
3315 if (child != NULL) {
3316 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3317 "Include has unexpected content\n", NULL, NULL);
3318 return (-1);
3319 }
3320
3321 /*
3322 * First step is to parse the input document into an DOM/Infoset
3323 */
3324 doc = xmlReadFile((const char *) schemaLocation, NULL,
3325 SCHEMAS_PARSE_OPTIONS);
3326 if (doc == NULL) {
3327 xmlSchemaPErr(ctxt, NULL,
3328 XML_SCHEMAP_FAILED_LOAD,
3329 "xmlSchemaParse: could not load %s\n",
3330 ctxt->URL, NULL);
3331 return(-1);
3332 }
3333
3334 /*
3335 * Then extract the root of the schema
3336 */
3337 root = xmlDocGetRootElement(doc);
3338 if (root == NULL) {
3339 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3340 XML_SCHEMAP_NOROOT,
3341 "schemas %s has no root", schemaLocation, NULL);
3342 xmlFreeDoc(doc);
3343 return (-1);
3344 }
3345
3346 /*
3347 * Remove all the blank text nodes
3348 */
3349 xmlSchemaCleanupDoc(ctxt, root);
3350
3351 /*
3352 * Check the schemas top level element
3353 */
3354 if (!IS_SCHEMA(root, "schema")) {
3355 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3356 XML_SCHEMAP_NOT_SCHEMA,
3357 "File %s is not a schemas", schemaLocation, NULL);
3358 xmlFreeDoc(doc);
3359 return (-1);
3360 }
3361
3362 /*
3363 * register the include
3364 */
3365 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3366 if (include == NULL) {
3367 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3368 xmlFreeDoc(doc);
3369 return (-1);
3370 }
3371
3372 memset(include, 0, sizeof(xmlSchemaInclude));
3373 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3374 include->doc = doc;
3375 include->next = schema->includes;
3376 schema->includes = include;
3377
3378
3379 /*
3380 * parse the declarations in the included file like if they
3381 * were in the original file.
3382 */
3383 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3384
3385 return (1);
3386}
3387
3388/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003389 * xmlSchemaParseChoice:
3390 * @ctxt: a schema validation context
3391 * @schema: the schema being built
3392 * @node: a subtree containing XML Schema informations
3393 *
3394 * parse a XML schema Choice definition
3395 * *WARNING* this interface is highly subject to change
3396 *
William M. Bracke7091952004-05-11 15:09:58 +00003397 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003398 * 1 in case of success.
3399 */
3400static xmlSchemaTypePtr
3401xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003402 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003403{
3404 xmlSchemaTypePtr type, subtype, last = NULL;
3405 xmlNodePtr child = NULL;
3406 xmlChar name[30];
3407
3408 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3409 return (NULL);
3410
3411
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003412 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003413 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003414 if (type == NULL)
3415 return (NULL);
3416 type->node = node;
3417 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003418 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003419 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3420 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3421
3422 child = node->children;
3423 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003424 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3425 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003426 }
3427 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003428 (IS_SCHEMA(child, "group")) ||
3429 (IS_SCHEMA(child, "any")) ||
3430 (IS_SCHEMA(child, "choice")) ||
3431 (IS_SCHEMA(child, "sequence"))) {
3432 subtype = NULL;
3433 if (IS_SCHEMA(child, "element")) {
3434 subtype = (xmlSchemaTypePtr)
3435 xmlSchemaParseElement(ctxt, schema, child, 0);
3436 } else if (IS_SCHEMA(child, "group")) {
3437 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3438 } else if (IS_SCHEMA(child, "any")) {
3439 subtype = xmlSchemaParseAny(ctxt, schema, child);
3440 } else if (IS_SCHEMA(child, "sequence")) {
3441 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3442 } else if (IS_SCHEMA(child, "choice")) {
3443 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3444 }
3445 if (subtype != NULL) {
3446 if (last == NULL) {
3447 type->subtypes = subtype;
3448 last = subtype;
3449 } else {
3450 last->next = subtype;
3451 last = subtype;
3452 }
3453 last->next = NULL;
3454 }
3455 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003456 }
3457 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003458 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3459 "Choice %s has unexpected content\n", type->name,
3460 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003461 }
3462
3463 return (type);
3464}
3465
3466/**
3467 * xmlSchemaParseSequence:
3468 * @ctxt: a schema validation context
3469 * @schema: the schema being built
3470 * @node: a subtree containing XML Schema informations
3471 *
3472 * parse a XML schema Sequence definition
3473 * *WARNING* this interface is highly subject to change
3474 *
William M. Bracke7091952004-05-11 15:09:58 +00003475 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003476 * 1 in case of success.
3477 */
3478static xmlSchemaTypePtr
3479xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003480 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003481{
3482 xmlSchemaTypePtr type, subtype, last = NULL;
3483 xmlNodePtr child = NULL;
3484 xmlChar name[30];
3485
3486 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3487 return (NULL);
3488
3489
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003490 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003491 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003492 if (type == NULL)
3493 return (NULL);
3494 type->node = node;
3495 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003496 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003497 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3498 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3499
3500 child = node->children;
3501 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003502 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3503 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003504 }
3505 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003506 (IS_SCHEMA(child, "group")) ||
3507 (IS_SCHEMA(child, "any")) ||
3508 (IS_SCHEMA(child, "choice")) ||
3509 (IS_SCHEMA(child, "sequence"))) {
3510 subtype = NULL;
3511 if (IS_SCHEMA(child, "element")) {
3512 subtype = (xmlSchemaTypePtr)
3513 xmlSchemaParseElement(ctxt, schema, child, 0);
3514 } else if (IS_SCHEMA(child, "group")) {
3515 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3516 } else if (IS_SCHEMA(child, "any")) {
3517 subtype = xmlSchemaParseAny(ctxt, schema, child);
3518 } else if (IS_SCHEMA(child, "choice")) {
3519 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3520 } else if (IS_SCHEMA(child, "sequence")) {
3521 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3522 }
3523 if (subtype != NULL) {
3524 if (last == NULL) {
3525 type->subtypes = subtype;
3526 last = subtype;
3527 } else {
3528 last->next = subtype;
3529 last = subtype;
3530 }
3531 last->next = NULL;
3532 }
3533 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003534 }
3535 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003536 xmlSchemaPErr2(ctxt, node, child,
3537 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3538 "Sequence %s has unexpected content\n", type->name,
3539 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003540 }
3541
3542 return (type);
3543}
3544
3545/**
3546 * xmlSchemaParseRestriction:
3547 * @ctxt: a schema validation context
3548 * @schema: the schema being built
3549 * @node: a subtree containing XML Schema informations
3550 * @simple: is that part of a simple type.
3551 *
3552 * parse a XML schema Restriction definition
3553 * *WARNING* this interface is highly subject to change
3554 *
3555 * Returns the type definition or NULL in case of error
3556 */
3557static xmlSchemaTypePtr
3558xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3559 xmlNodePtr node, int simple)
3560{
3561 xmlSchemaTypePtr type, subtype;
3562 xmlSchemaFacetPtr facet, lastfacet = NULL;
3563 xmlNodePtr child = NULL;
3564 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003565 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003566
3567 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3568 return (NULL);
3569
3570 oldcontainer = ctxt->container;
3571
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003572 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003573 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003574 if (type == NULL)
3575 return (NULL);
3576 type->node = node;
3577 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003578 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003579 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3580 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003581 xmlSchemaPErr2(ctxt, node, child,
3582 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
3583 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003584 }
3585 ctxt->container = name;
3586
3587 child = node->children;
3588 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003589 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3590 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003591 }
3592 subtype = NULL;
3593
3594 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003595 subtype = (xmlSchemaTypePtr)
3596 xmlSchemaParseAll(ctxt, schema, child);
3597 child = child->next;
3598 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003599 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003600 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3601 child = child->next;
3602 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003603 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003604 subtype = (xmlSchemaTypePtr)
3605 xmlSchemaParseSequence(ctxt, schema, child);
3606 child = child->next;
3607 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003608 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003609 subtype = (xmlSchemaTypePtr)
3610 xmlSchemaParseGroup(ctxt, schema, child);
3611 child = child->next;
3612 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003613 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003614 if (IS_SCHEMA(child, "simpleType")) {
3615 subtype = (xmlSchemaTypePtr)
3616 xmlSchemaParseSimpleType(ctxt, schema, child);
3617 child = child->next;
3618 type->baseType = subtype;
3619 }
3620 /*
3621 * Facets
3622 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003624 (IS_SCHEMA(child, "minExclusive")) ||
3625 (IS_SCHEMA(child, "maxInclusive")) ||
3626 (IS_SCHEMA(child, "maxExclusive")) ||
3627 (IS_SCHEMA(child, "totalDigits")) ||
3628 (IS_SCHEMA(child, "fractionDigits")) ||
3629 (IS_SCHEMA(child, "pattern")) ||
3630 (IS_SCHEMA(child, "enumeration")) ||
3631 (IS_SCHEMA(child, "whiteSpace")) ||
3632 (IS_SCHEMA(child, "length")) ||
3633 (IS_SCHEMA(child, "maxLength")) ||
3634 (IS_SCHEMA(child, "minLength"))) {
3635 facet = xmlSchemaParseFacet(ctxt, schema, child);
3636 if (facet != NULL) {
3637 if (lastfacet == NULL) {
3638 type->facets = facet;
3639 lastfacet = facet;
3640 } else {
3641 lastfacet->next = facet;
3642 lastfacet = facet;
3643 }
3644 lastfacet->next = NULL;
3645 }
3646 child = child->next;
3647 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 }
3649 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3650 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003651 xmlSchemaPErr2(ctxt, node, child,
3652 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
3653 "Restriction %s has unexpected content\n",
3654 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003655 }
3656 ctxt->container = oldcontainer;
3657 return (type);
3658}
3659
3660/**
3661 * xmlSchemaParseExtension:
3662 * @ctxt: a schema validation context
3663 * @schema: the schema being built
3664 * @node: a subtree containing XML Schema informations
3665 *
3666 * parse a XML schema Extension definition
3667 * *WARNING* this interface is highly subject to change
3668 *
3669 * Returns the type definition or NULL in case of error
3670 */
3671static xmlSchemaTypePtr
3672xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003673 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003674{
3675 xmlSchemaTypePtr type, subtype;
3676 xmlNodePtr child = NULL;
3677 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003678 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003679
3680 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3681 return (NULL);
3682
3683 oldcontainer = ctxt->container;
3684
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003685 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003686 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003687 if (type == NULL)
3688 return (NULL);
3689 type->node = node;
3690 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003691 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003692 ctxt->container = name;
3693
3694 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3695 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003696 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3697 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003698 }
3699 child = node->children;
3700 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003701 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3702 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003703 }
3704 subtype = NULL;
3705
3706 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003707 subtype = xmlSchemaParseAll(ctxt, schema, child);
3708 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003709 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003710 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3711 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003712 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003713 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3714 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003715 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003716 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3717 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003718 }
3719 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003720 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003721 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3722 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003723 xmlSchemaPErr2(ctxt, node, child,
3724 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3725 "Extension %s has unexpected content\n", type->name,
3726 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003727 }
3728 ctxt->container = oldcontainer;
3729 return (type);
3730}
3731
3732/**
3733 * xmlSchemaParseSimpleContent:
3734 * @ctxt: a schema validation context
3735 * @schema: the schema being built
3736 * @node: a subtree containing XML Schema informations
3737 *
3738 * parse a XML schema SimpleContent definition
3739 * *WARNING* this interface is highly subject to change
3740 *
3741 * Returns the type definition or NULL in case of error
3742 */
3743static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003744xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3745 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003746{
3747 xmlSchemaTypePtr type, subtype;
3748 xmlNodePtr child = NULL;
3749 xmlChar name[30];
3750
3751 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3752 return (NULL);
3753
3754
William M. Bracke7091952004-05-11 15:09:58 +00003755 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003756 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003757 if (type == NULL)
3758 return (NULL);
3759 type->node = node;
3760 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003761 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003762
3763 child = node->children;
3764 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003765 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3766 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003767 }
3768 subtype = NULL;
3769 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003770 subtype = (xmlSchemaTypePtr)
3771 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3772 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003773 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003774 subtype = (xmlSchemaTypePtr)
3775 xmlSchemaParseExtension(ctxt, schema, child);
3776 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003777 }
3778 type->subtypes = subtype;
3779 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003780 xmlSchemaPErr2(ctxt, node, child,
3781 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3782 "SimpleContent %s has unexpected content\n",
3783 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003784 }
3785 return (type);
3786}
3787
3788/**
3789 * xmlSchemaParseComplexContent:
3790 * @ctxt: a schema validation context
3791 * @schema: the schema being built
3792 * @node: a subtree containing XML Schema informations
3793 *
3794 * parse a XML schema ComplexContent definition
3795 * *WARNING* this interface is highly subject to change
3796 *
3797 * Returns the type definition or NULL in case of error
3798 */
3799static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003800xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3801 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003802{
3803 xmlSchemaTypePtr type, subtype;
3804 xmlNodePtr child = NULL;
3805 xmlChar name[30];
3806
3807 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3808 return (NULL);
3809
3810
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003811 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003812 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003813 if (type == NULL)
3814 return (NULL);
3815 type->node = node;
3816 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003817 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003818
3819 child = node->children;
3820 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003821 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3822 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003823 }
3824 subtype = NULL;
3825 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003826 subtype = (xmlSchemaTypePtr)
3827 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3828 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003829 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003830 subtype = (xmlSchemaTypePtr)
3831 xmlSchemaParseExtension(ctxt, schema, child);
3832 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003833 }
3834 type->subtypes = subtype;
3835 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003836 xmlSchemaPErr2(ctxt, node, child,
3837 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3838 "ComplexContent %s has unexpected content\n",
3839 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003840 }
3841 return (type);
3842}
3843
3844/**
3845 * xmlSchemaParseComplexType:
3846 * @ctxt: a schema validation context
3847 * @schema: the schema being built
3848 * @node: a subtree containing XML Schema informations
3849 *
3850 * parse a XML schema Complex Type definition
3851 * *WARNING* this interface is highly subject to change
3852 *
3853 * Returns the type definition or NULL in case of error
3854 */
3855static xmlSchemaTypePtr
3856xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3857 xmlNodePtr node)
3858{
3859 xmlSchemaTypePtr type, subtype;
3860 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003861 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00003862 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003863 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003864
3865 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3866 return (NULL);
3867
3868 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003869 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003870 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003871
William M. Bracke7091952004-05-11 15:09:58 +00003872 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003873 name = (const xmlChar *)buf;
3874 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3875 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003876
William M. Bracke7091952004-05-11 15:09:58 +00003877 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
3878 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003879 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003880 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003881 return (NULL);
3882 }
Daniel Veillard1aefc862004-03-04 11:40:48 +00003883
William M. Bracke7091952004-05-11 15:09:58 +00003884 if (xmlGetBooleanProp(ctxt, node, "mixed", 0))
3885 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00003886
Daniel Veillard4255d502002-04-16 15:50:10 +00003887 type->node = node;
3888 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003889 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003890 ctxt->container = name;
3891
3892 child = node->children;
3893 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003894 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3895 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003896 }
3897 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00003898 /* 3.4.3 : 2.2
3899 * Specifying mixed='true' when the <simpleContent>
3900 * alternative is chosen has no effect
3901 */
3902 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
3903 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003904 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3905 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003906 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003907 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3908 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003909 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003910 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003911
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003912 if (IS_SCHEMA(child, "all")) {
3913 subtype = xmlSchemaParseAll(ctxt, schema, child);
3914 child = child->next;
3915 } else if (IS_SCHEMA(child, "choice")) {
3916 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3917 child = child->next;
3918 } else if (IS_SCHEMA(child, "sequence")) {
3919 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3920 child = child->next;
3921 } else if (IS_SCHEMA(child, "group")) {
3922 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3923 child = child->next;
3924 }
3925 if (subtype != NULL)
3926 type->subtypes = subtype;
3927 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003928 }
3929 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003930 xmlSchemaPErr2(ctxt, node, child,
3931 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3932 "ComplexType %s has unexpected content\n",
3933 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003934 }
3935 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003936 return (type);
3937}
3938
Daniel Veillard4255d502002-04-16 15:50:10 +00003939/**
3940 * xmlSchemaParseSchema:
3941 * @ctxt: a schema validation context
3942 * @node: a subtree containing XML Schema informations
3943 *
3944 * parse a XML schema definition from a node set
3945 * *WARNING* this interface is highly subject to change
3946 *
3947 * Returns the internal XML Schema structure built from the resource or
3948 * NULL in case of error
3949 */
3950static xmlSchemaPtr
3951xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3952{
3953 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003954 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003955 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003956 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003957
3958 if ((ctxt == NULL) || (node == NULL))
3959 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00003960
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003961 nberrors = ctxt->nberrors;
3962 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003963 if (IS_SCHEMA(node, "schema")) {
3964 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003965 if (schema == NULL)
3966 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003967 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3968 if (val != NULL) {
3969 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3970 } else {
3971 schema->targetNamespace = NULL;
3972 }
3973 schema->id = xmlSchemaGetProp(ctxt, node, "id");
3974 schema->version = xmlSchemaGetProp(ctxt, node, "version");
3975 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003976 if (val != NULL) {
3977 if (xmlStrEqual(val, BAD_CAST "qualified"))
3978 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3979 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3980 xmlSchemaPErr2(ctxt, node, child,
3981 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3982 "Invalid value %s for elementFormDefault\n",
3983 val, NULL);
3984 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003985 } else {
3986 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3987 }
3988 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003989 if (val != NULL) {
3990 if (xmlStrEqual(val, BAD_CAST "qualified"))
3991 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3992 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3993 xmlSchemaPErr2(ctxt, node, child,
3994 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3995 "Invalid value %s for attributeFormDefault\n",
3996 val, NULL);
3997 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003998 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003999
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004000 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
4001 } else {
4002 xmlDocPtr doc;
4003
4004 doc = node->doc;
4005
4006 if ((doc != NULL) && (doc->URL != NULL)) {
4007 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4008 XML_SCHEMAP_NOT_SCHEMA,
4009 "File %s is not a schemas", doc->URL, NULL);
4010 } else {
4011 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4012 XML_SCHEMAP_NOT_SCHEMA,
4013 "File is not a schemas", NULL, NULL);
4014 }
4015 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004016 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004017 if (ctxt->nberrors != 0) {
4018 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004019 xmlSchemaFree(schema);
4020 schema = NULL;
4021 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004022 }
4023 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004024#ifdef DEBUG
4025 if (schema == NULL)
4026 xmlGenericError(xmlGenericErrorContext,
4027 "xmlSchemaParse() failed\n");
4028#endif
4029
4030 return (schema);
4031}
4032
4033/************************************************************************
4034 * *
4035 * Validating using Schemas *
4036 * *
4037 ************************************************************************/
4038
4039/************************************************************************
4040 * *
4041 * Reading/Writing Schemas *
4042 * *
4043 ************************************************************************/
4044
4045/**
4046 * xmlSchemaNewParserCtxt:
4047 * @URL: the location of the schema
4048 *
4049 * Create an XML Schemas parse context for that file/resource expected
4050 * to contain an XML Schemas file.
4051 *
4052 * Returns the parser context or NULL in case of error
4053 */
4054xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004055xmlSchemaNewParserCtxt(const char *URL)
4056{
Daniel Veillard4255d502002-04-16 15:50:10 +00004057 xmlSchemaParserCtxtPtr ret;
4058
4059 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004060 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004061
4062 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4063 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004064 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4065 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004066 return (NULL);
4067 }
4068 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004069 ret->dict = xmlDictCreate();
4070 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004071 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004072 return (ret);
4073}
4074
4075/**
Daniel Veillard6045c902002-10-09 21:13:59 +00004076 * xmlSchemaNewMemParserCtxt:
4077 * @buffer: a pointer to a char array containing the schemas
4078 * @size: the size of the array
4079 *
4080 * Create an XML Schemas parse context for that memory buffer expected
4081 * to contain an XML Schemas file.
4082 *
4083 * Returns the parser context or NULL in case of error
4084 */
4085xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004086xmlSchemaNewMemParserCtxt(const char *buffer, int size)
4087{
Daniel Veillard6045c902002-10-09 21:13:59 +00004088 xmlSchemaParserCtxtPtr ret;
4089
4090 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004091 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00004092
4093 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4094 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004095 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4096 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00004097 return (NULL);
4098 }
4099 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4100 ret->buffer = buffer;
4101 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00004102 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00004103 return (ret);
4104}
4105
4106/**
Daniel Veillard9d751502003-10-29 13:21:47 +00004107 * xmlSchemaNewDocParserCtxt:
4108 * @doc: a preparsed document tree
4109 *
4110 * Create an XML Schemas parse context for that document.
4111 * NB. The document may be modified during the parsing process.
4112 *
4113 * Returns the parser context or NULL in case of error
4114 */
4115xmlSchemaParserCtxtPtr
4116xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
4117{
4118 xmlSchemaParserCtxtPtr ret;
4119
4120 if (doc == NULL)
4121 return (NULL);
4122
4123 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4124 if (ret == NULL) {
4125 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
4126 NULL);
4127 return (NULL);
4128 }
4129 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4130 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00004131 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00004132 /* The application has responsibility for the document */
4133 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00004134
4135 return (ret);
4136}
4137
4138/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004139 * xmlSchemaFreeParserCtxt:
4140 * @ctxt: the schema parser context
4141 *
4142 * Free the resources associated to the schema parser context
4143 */
4144void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004145xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
4146{
Daniel Veillard4255d502002-04-16 15:50:10 +00004147 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004148 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004149 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004150 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004151 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004152 xmlFree(ctxt);
4153}
4154
4155/************************************************************************
4156 * *
4157 * Building the content models *
4158 * *
4159 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004160
Daniel Veillard4255d502002-04-16 15:50:10 +00004161/**
4162 * xmlSchemaBuildAContentModel:
4163 * @type: the schema type definition
4164 * @ctxt: the schema parser context
4165 * @name: the element name whose content is being built
4166 *
4167 * Generate the automata sequence needed for that type
4168 */
4169static void
4170xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004171 xmlSchemaParserCtxtPtr ctxt,
4172 const xmlChar * name)
4173{
Daniel Veillard4255d502002-04-16 15:50:10 +00004174 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004175 xmlGenericError(xmlGenericErrorContext,
4176 "Found unexpected type = NULL in %s content model\n",
4177 name);
4178 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004179 }
4180 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004181 case XML_SCHEMA_TYPE_ANY:
4182 /* TODO : handle the namespace too */
4183 /* TODO : make that a specific transition type */
4184 TODO ctxt->state =
4185 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
4186 BAD_CAST "*", NULL);
4187 break;
4188 case XML_SCHEMA_TYPE_ELEMENT:{
4189 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00004190
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004191 /* TODO : handle the namespace too */
4192 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004193
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004194 if (elem->maxOccurs >= UNBOUNDED) {
4195 if (elem->minOccurs > 1) {
4196 xmlAutomataStatePtr tmp;
4197 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00004198
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004199 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4200 oldstate,
4201 NULL);
4202 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004203
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004204 counter = xmlAutomataNewCounter(ctxt->am,
4205 elem->minOccurs -
4206 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00004207
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004208 if (elem->refDecl != NULL) {
4209 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4210 elem->refDecl,
4211 ctxt,
4212 elem->refDecl->
4213 name);
4214 } else {
4215 ctxt->state =
4216 xmlAutomataNewTransition(ctxt->am,
4217 ctxt->state, NULL,
4218 elem->name, type);
4219 }
4220 tmp = ctxt->state;
4221 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4222 counter);
4223 ctxt->state =
4224 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4225 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00004226
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004227 } else {
4228 if (elem->refDecl != NULL) {
4229 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4230 elem->refDecl,
4231 ctxt,
4232 elem->refDecl->
4233 name);
4234 } else {
4235 ctxt->state =
4236 xmlAutomataNewTransition(ctxt->am,
4237 ctxt->state, NULL,
4238 elem->name, type);
4239 }
4240 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4241 oldstate);
4242 if (elem->minOccurs == 0) {
4243 /* basically an elem* */
4244 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4245 ctxt->state);
4246 }
4247 }
4248 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
4249 xmlAutomataStatePtr tmp;
4250 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00004251
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004252 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4253 oldstate, NULL);
4254 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004255
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004256 counter = xmlAutomataNewCounter(ctxt->am,
4257 elem->minOccurs - 1,
4258 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004259
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004260 if (elem->refDecl != NULL) {
4261 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4262 elem->refDecl, ctxt,
4263 elem->refDecl->name);
4264 } else {
4265 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4266 ctxt->state,
4267 NULL,
4268 elem->name,
4269 type);
4270 }
4271 tmp = ctxt->state;
4272 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4273 counter);
4274 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
4275 NULL,
4276 counter);
4277 if (elem->minOccurs == 0) {
4278 /* basically an elem? */
4279 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4280 ctxt->state);
4281 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00004282
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004283 } else {
4284 if (elem->refDecl != NULL) {
4285 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4286 elem->refDecl, ctxt,
4287 elem->refDecl->name);
4288 } else {
4289 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4290 ctxt->state,
4291 NULL,
4292 elem->name,
4293 type);
4294 }
4295 if (elem->minOccurs == 0) {
4296 /* basically an elem? */
4297 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4298 ctxt->state);
4299 }
4300 }
4301 break;
4302 }
4303 case XML_SCHEMA_TYPE_SEQUENCE:{
4304 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004305
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004306 /*
4307 * If max and min occurances are default (1) then
4308 * simply iterate over the subtypes
4309 */
4310 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4311 subtypes = type->subtypes;
4312 while (subtypes != NULL) {
4313 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4314 subtypes = subtypes->next;
4315 }
4316 } else {
4317 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004318
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004319 if (type->maxOccurs >= UNBOUNDED) {
4320 if (type->minOccurs > 1) {
4321 xmlAutomataStatePtr tmp;
4322 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004323
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004324 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4325 oldstate,
4326 NULL);
4327 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004328
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004329 counter = xmlAutomataNewCounter(ctxt->am,
4330 type->
4331 minOccurs - 1,
4332 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004333
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004334 subtypes = type->subtypes;
4335 while (subtypes != NULL) {
4336 xmlSchemaBuildAContentModel(subtypes, ctxt,
4337 name);
4338 subtypes = subtypes->next;
4339 }
4340 tmp = ctxt->state;
4341 xmlAutomataNewCountedTrans(ctxt->am, tmp,
4342 oldstate, counter);
4343 ctxt->state =
4344 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4345 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004346
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004347 } else {
4348 subtypes = type->subtypes;
4349 while (subtypes != NULL) {
4350 xmlSchemaBuildAContentModel(subtypes, ctxt,
4351 name);
4352 subtypes = subtypes->next;
4353 }
4354 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4355 oldstate);
4356 if (type->minOccurs == 0) {
4357 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4358 ctxt->state);
4359 }
4360 }
4361 } else if ((type->maxOccurs > 1)
4362 || (type->minOccurs > 1)) {
4363 xmlAutomataStatePtr tmp;
4364 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004365
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004366 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4367 oldstate,
4368 NULL);
4369 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00004370
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004371 counter = xmlAutomataNewCounter(ctxt->am,
4372 type->minOccurs -
4373 1,
4374 type->maxOccurs -
4375 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004376
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004377 subtypes = type->subtypes;
4378 while (subtypes != NULL) {
4379 xmlSchemaBuildAContentModel(subtypes, ctxt,
4380 name);
4381 subtypes = subtypes->next;
4382 }
4383 tmp = ctxt->state;
4384 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4385 counter);
4386 ctxt->state =
4387 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4388 counter);
4389 if (type->minOccurs == 0) {
4390 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4391 ctxt->state);
4392 }
Daniel Veillardb509f152002-04-17 16:28:10 +00004393
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004394 } else {
4395 subtypes = type->subtypes;
4396 while (subtypes != NULL) {
4397 xmlSchemaBuildAContentModel(subtypes, ctxt,
4398 name);
4399 subtypes = subtypes->next;
4400 }
4401 if (type->minOccurs == 0) {
4402 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4403 ctxt->state);
4404 }
4405 }
4406 }
4407 break;
4408 }
4409 case XML_SCHEMA_TYPE_CHOICE:{
4410 xmlSchemaTypePtr subtypes;
4411 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00004412
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004413 start = ctxt->state;
4414 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00004415
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004416 /*
4417 * iterate over the subtypes and remerge the end with an
4418 * epsilon transition
4419 */
4420 if (type->maxOccurs == 1) {
4421 subtypes = type->subtypes;
4422 while (subtypes != NULL) {
4423 ctxt->state = start;
4424 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4425 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4426 subtypes = subtypes->next;
4427 }
4428 } else {
4429 int counter;
4430 xmlAutomataStatePtr hop;
4431 int maxOccurs = type->maxOccurs == UNBOUNDED ?
4432 UNBOUNDED : type->maxOccurs - 1;
4433 int minOccurs =
4434 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00004435
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004436 /*
4437 * use a counter to keep track of the number of transtions
4438 * which went through the choice.
4439 */
4440 counter =
4441 xmlAutomataNewCounter(ctxt->am, minOccurs,
4442 maxOccurs);
4443 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00004444
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004445 subtypes = type->subtypes;
4446 while (subtypes != NULL) {
4447 ctxt->state = start;
4448 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4449 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4450 subtypes = subtypes->next;
4451 }
4452 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4453 counter);
4454 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4455 counter);
4456 }
4457 if (type->minOccurs == 0) {
4458 xmlAutomataNewEpsilon(ctxt->am, start, end);
4459 }
4460 ctxt->state = end;
4461 break;
4462 }
4463 case XML_SCHEMA_TYPE_ALL:{
4464 xmlAutomataStatePtr start;
4465 xmlSchemaTypePtr subtypes;
4466 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4467 int lax;
4468
4469 subtypes = type->subtypes;
4470 if (subtypes == NULL)
4471 break;
4472 start = ctxt->state;
4473 while (subtypes != NULL) {
4474 ctxt->state = start;
William M. Bracke7091952004-05-11 15:09:58 +00004475 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004476 /* TODO : handle the namespace too */
4477 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4478 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4479 ctxt->state, elem->name, 1,
4480 1, subtypes);
4481 } else {
4482 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4483 ctxt->state, elem->name,
4484 elem->minOccurs,
4485 elem->maxOccurs,
4486 subtypes);
4487 }
4488 subtypes = subtypes->next;
4489 }
4490 lax = type->minOccurs == 0;
4491 ctxt->state =
4492 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4493 lax);
4494 break;
4495 }
4496 case XML_SCHEMA_TYPE_RESTRICTION:
4497 if (type->subtypes != NULL)
4498 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4499 break;
4500 case XML_SCHEMA_TYPE_EXTENSION:
4501 if (type->baseType != NULL) {
4502 xmlSchemaTypePtr subtypes;
4503
Daniel Veillardf7627552004-04-22 07:15:40 +00004504 if (type->recurse) {
4505 xmlSchemaPErr(ctxt, type->node,
4506 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4507 "Schemas: extension type %s is recursive\n",
4508 type->name, NULL);
4509 return;
4510 }
4511 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004512 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00004513 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004514 subtypes = type->subtypes;
4515 while (subtypes != NULL) {
4516 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4517 subtypes = subtypes->next;
4518 }
4519 } else if (type->subtypes != NULL)
4520 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4521 break;
4522 case XML_SCHEMA_TYPE_GROUP:
4523 if (type->subtypes == NULL) {
4524 }
4525 case XML_SCHEMA_TYPE_COMPLEX:
4526 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4527 if (type->subtypes != NULL)
4528 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4529 break;
4530 default:
4531 xmlGenericError(xmlGenericErrorContext,
4532 "Found unexpected type %d in %s content model\n",
4533 type->type, name);
4534 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004535 }
4536}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004537
Daniel Veillard4255d502002-04-16 15:50:10 +00004538/**
4539 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004540 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00004541 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004542 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00004543 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004544 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00004545 */
4546static void
4547xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004548 xmlSchemaParserCtxtPtr ctxt,
4549 const xmlChar * name)
4550{
Daniel Veillard4255d502002-04-16 15:50:10 +00004551 xmlAutomataStatePtr start;
4552
Daniel Veillard4255d502002-04-16 15:50:10 +00004553 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004554 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004555 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004556 elem->contentType = XML_SCHEMA_CONTENT_ANY;
4557 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004558 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004559 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004560 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004561 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
4562 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004563 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004564
4565#ifdef DEBUG_CONTENT
4566 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004567 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004568#endif
4569
Daniel Veillard4255d502002-04-16 15:50:10 +00004570 ctxt->am = xmlNewAutomata();
4571 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004572 xmlGenericError(xmlGenericErrorContext,
4573 "Cannot create automata for elem %s\n", name);
4574 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004575 }
4576 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
4577 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
4578 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00004579 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004580 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004581 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
4582 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004583 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004584 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
4585 "Content model of %s is not determinist:\n", name,
4586 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00004587 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00004588#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004589 xmlGenericError(xmlGenericErrorContext,
4590 "Content model of %s:\n", name);
4591 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004592#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00004593 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004594 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004595 xmlFreeAutomata(ctxt->am);
4596 ctxt->am = NULL;
4597}
4598
4599/**
4600 * xmlSchemaRefFixupCallback:
4601 * @elem: the schema element context
4602 * @ctxt: the schema parser context
4603 *
4604 * Free the resources associated to the schema parser context
4605 */
4606static void
4607xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004608 xmlSchemaParserCtxtPtr ctxt,
4609 const xmlChar * name,
4610 const xmlChar * context ATTRIBUTE_UNUSED,
4611 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004612{
4613 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004614 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004615 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004616 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004617
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004618 if (elem->subtypes != NULL) {
4619 xmlSchemaPErr(ctxt, elem->node,
4620 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
4621 "Schemas: element %s have both ref and subtype\n",
4622 name, NULL);
4623 return;
4624 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004625 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004626
4627 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004628 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
4629 "Schemas: element %s ref to %s not found\n",
4630 name, elem->ref);
4631 return;
4632 }
4633 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004634 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004635 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004636
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004637 if (elem->subtypes != NULL) {
4638 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
4639 "Schemas: element %s have both type and subtype\n",
4640 name, NULL);
4641 return;
4642 }
4643 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
4644 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00004645
4646 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004647 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
4648 "Schemas: element %s type %s not found\n", name,
4649 elem->namedType);
4650 return;
4651 }
4652 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004653 }
4654}
4655
William M. Bracke7091952004-05-11 15:09:58 +00004656/**
4657 * xmlSchemaParseListRefFixup:
4658 * @type: the schema type definition
4659 * @ctxt: the schema parser context
4660 *
4661 * Fixup of the itemType reference of the list type.
4662 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00004663static void
William M. Bracke7091952004-05-11 15:09:58 +00004664xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
4665{
4666 const xmlChar *itemType, *namespace;
4667 xmlSchemaTypePtr subtype;
4668
4669 /* Handle the "itemType" attribute. */
4670 itemType = xmlGetQNameProp(ctxt, type->node, BAD_CAST "itemType", &namespace);
4671 if (itemType != NULL) {
4672 /* Do not allow more that one item type. */
4673 if (type->subtypes != NULL) {
4674 xmlSchemaPErr(ctxt, type->node,
4675 XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE,
4676 "List %s has more than one item type defined\n",
4677 type->name, NULL);
4678 }
4679 subtype = xmlSchemaGetType(ctxt->schema, itemType, namespace);
4680 if (subtype == NULL) {
4681 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_TYPE,
4682 "List %s references an unknown item type: %s\n",
4683 type->name, xmlSchemaGetProp(ctxt, type->node,
4684 BAD_CAST "itemType"));
4685 } else
4686 type->subtypes = subtype;
4687 }
4688}
4689
4690/**
4691 * xmlSchemaParseUnionRefCheck:
4692 * @typeDecl: the schema type definition
4693 * @ctxt: the schema parser context
4694 *
4695 * Checks the memberTypes references of the union type.
4696 */
4697static void
4698xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00004699 xmlSchemaParserCtxtPtr ctxt)
4700{
4701 const xmlChar *cur, *end, *prefix, *ncName, *namespace;
4702 xmlChar *tmp;
4703 xmlSchemaTypePtr subtype;
4704 xmlNsPtr ns;
4705 int len;
4706
William M. Bracke7091952004-05-11 15:09:58 +00004707 if ((type->type != XML_SCHEMA_TYPE_UNION) || (type->ref == NULL))
Daniel Veillard377e1a92004-04-16 16:30:05 +00004708 return;
4709
William M. Bracke7091952004-05-11 15:09:58 +00004710 cur = type->ref;
Daniel Veillard377e1a92004-04-16 16:30:05 +00004711 do {
4712 while (IS_BLANK_CH(*cur))
4713 cur++;
4714 end = cur;
4715 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4716 end++;
4717 if (end == cur)
4718 break;
4719 tmp = xmlStrndup(cur, end - cur);
4720 ncName = xmlSplitQName3(tmp, &len);
4721 if (ncName != NULL) {
4722 prefix = xmlDictLookup(ctxt->dict, tmp, len);
4723 } else {
4724 prefix = NULL;
4725 ncName = tmp;
4726 }
William M. Bracke7091952004-05-11 15:09:58 +00004727 ns = xmlSearchNs(type->node->doc, type->node, prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004728 if (ns == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00004729 if (prefix != NULL) {
4730 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_PREFIX_UNDEFINED,
4731 "Union %s: the namespace prefix of member type "
4732 "%s is undefined\n",
4733 type->name, (const xmlChar *) tmp);
4734 }
4735 namespace = NULL;
Daniel Veillard377e1a92004-04-16 16:30:05 +00004736 } else {
4737 namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4738 }
4739 /* Lookup the referenced type */
4740 subtype = xmlSchemaGetType(ctxt->schema, ncName, namespace);
4741 if (subtype == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00004742 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
4743 "Union %s references an unknown member type %s\n",
4744 type->name, (const xmlChar *) tmp);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004745 }
William M. Bracke7091952004-05-11 15:09:58 +00004746 xmlFree(tmp);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004747 cur = end;
William M. Bracke7091952004-05-11 15:09:58 +00004748 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004749}
4750
Daniel Veillard4255d502002-04-16 15:50:10 +00004751/**
4752 * xmlSchemaTypeFixup:
4753 * @typeDecl: the schema type definition
4754 * @ctxt: the schema parser context
4755 *
4756 * Fixes the content model of the type.
4757 */
4758static void
4759xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004760 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004761{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00004762 if (typeDecl == NULL)
4763 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004764 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004765 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004766 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004767 switch (typeDecl->type) {
4768 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4769 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4770 if (typeDecl->subtypes != NULL)
4771 typeDecl->contentType =
4772 typeDecl->subtypes->contentType;
4773 break;
4774 }
4775 case XML_SCHEMA_TYPE_RESTRICTION:{
4776 if (typeDecl->subtypes != NULL)
4777 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004778
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004779 if (typeDecl->base != NULL) {
4780 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004781
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004782 baseType =
4783 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4784 typeDecl->baseNs);
4785 if (baseType == NULL) {
4786 xmlSchemaPErr(ctxt, typeDecl->node,
4787 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004788 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004789 name, typeDecl->base);
4790 }
4791 typeDecl->baseType = baseType;
4792 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004793 if (typeDecl->subtypes == NULL)
William M. Bracke7091952004-05-11 15:09:58 +00004794 if (typeDecl->baseType != NULL) {
4795 /* The base type might be not "type fixed" yet,
4796 * so do it now. */
4797 if (typeDecl->baseType->contentType ==
4798 XML_SCHEMA_CONTENT_UNKNOWN)
4799 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004800 typeDecl->contentType =
4801 typeDecl->baseType->contentType;
William M. Bracke7091952004-05-11 15:09:58 +00004802 } else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004803 /* 1.1.1 */
4804 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004805 else if ((typeDecl->subtypes->subtypes == NULL) &&
4806 ((typeDecl->subtypes->type ==
4807 XML_SCHEMA_TYPE_ALL)
4808 || (typeDecl->subtypes->type ==
4809 XML_SCHEMA_TYPE_SEQUENCE)))
4810 /* 1.1.2 */
4811 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4812 else if ((typeDecl->subtypes->type ==
4813 XML_SCHEMA_TYPE_CHOICE)
4814 && (typeDecl->subtypes->subtypes == NULL))
4815 /* 1.1.3 */
4816 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4817 else {
4818 /* 1.2 and 2.X are applied at the other layer */
4819 typeDecl->contentType =
4820 XML_SCHEMA_CONTENT_ELEMENTS;
4821 }
4822 break;
4823 }
4824 case XML_SCHEMA_TYPE_EXTENSION:{
4825 xmlSchemaContentType explicitContentType;
4826 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004827
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004828 if (typeDecl->base != NULL) {
4829 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004830
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004831 baseType =
4832 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4833 typeDecl->baseNs);
4834 if (baseType == NULL) {
4835 xmlSchemaPErr(ctxt, typeDecl->node,
4836 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004837 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004838 name, typeDecl->base);
4839 }
4840 typeDecl->baseType = baseType;
4841 }
4842 if (typeDecl->subtypes != NULL)
4843 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004844
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004845 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4846 if (typeDecl->subtypes == NULL)
4847 /* 1.1.1 */
4848 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4849 else if ((typeDecl->subtypes->subtypes == NULL) &&
4850 ((typeDecl->subtypes->type ==
4851 XML_SCHEMA_TYPE_ALL)
4852 || (typeDecl->subtypes->type ==
4853 XML_SCHEMA_TYPE_SEQUENCE)))
4854 /* 1.1.2 */
4855 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4856 else if ((typeDecl->subtypes->type ==
4857 XML_SCHEMA_TYPE_CHOICE)
4858 && (typeDecl->subtypes->subtypes == NULL))
4859 /* 1.1.3 */
4860 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004861
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004862 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4863 typeDecl->baseNs);
4864 if (base == NULL) {
4865 xmlSchemaPErr(ctxt, typeDecl->node,
4866 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4867 "Schemas: base type %s of type %s not found\n",
4868 typeDecl->base, name);
4869 return;
4870 }
Daniel Veillard2582a332004-04-18 19:49:46 +00004871 if (typeDecl->recurse) {
4872 xmlSchemaPErr(ctxt, typeDecl->node,
4873 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4874 "Schemas: extension type %s is recursive\n",
4875 name, NULL);
4876 return;
4877 }
4878 typeDecl->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004879 xmlSchemaTypeFixup(base, ctxt, NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +00004880 typeDecl->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004881 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4882 /* 2.1 */
4883 typeDecl->contentType = base->contentType;
4884 } else if (base->contentType ==
4885 XML_SCHEMA_CONTENT_EMPTY) {
4886 /* 2.2 imbitable ! */
4887 typeDecl->contentType =
4888 XML_SCHEMA_CONTENT_ELEMENTS;
4889 } else {
4890 /* 2.3 imbitable pareil ! */
4891 typeDecl->contentType =
4892 XML_SCHEMA_CONTENT_ELEMENTS;
4893 }
4894 break;
4895 }
4896 case XML_SCHEMA_TYPE_COMPLEX:{
4897 if (typeDecl->subtypes == NULL) {
4898 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004899
4900 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4901 typeDecl->contentType =
4902 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004903 } else {
4904 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4905 typeDecl->contentType =
4906 XML_SCHEMA_CONTENT_MIXED;
4907 else {
4908 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4909 NULL);
4910 if (typeDecl->subtypes != NULL)
4911 typeDecl->contentType =
4912 typeDecl->subtypes->contentType;
4913 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004914 if (typeDecl->attributes == NULL)
4915 typeDecl->attributes =
4916 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004917 }
4918 break;
4919 }
4920 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4921 if (typeDecl->subtypes == NULL) {
4922 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004923 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4924 typeDecl->contentType =
4925 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004926 } else {
4927 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4928 typeDecl->contentType =
4929 XML_SCHEMA_CONTENT_MIXED;
4930 else {
4931 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4932 NULL);
4933 if (typeDecl->subtypes != NULL)
4934 typeDecl->contentType =
4935 typeDecl->subtypes->contentType;
4936 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004937 if (typeDecl->attributes == NULL)
4938 typeDecl->attributes =
4939 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004940 }
4941 break;
4942 }
4943 case XML_SCHEMA_TYPE_SEQUENCE:
4944 case XML_SCHEMA_TYPE_GROUP:
4945 case XML_SCHEMA_TYPE_ALL:
4946 case XML_SCHEMA_TYPE_CHOICE:
4947 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4948 break;
4949 case XML_SCHEMA_TYPE_BASIC:
4950 case XML_SCHEMA_TYPE_ANY:
4951 case XML_SCHEMA_TYPE_FACET:
4952 case XML_SCHEMA_TYPE_SIMPLE:
4953 case XML_SCHEMA_TYPE_UR:
4954 case XML_SCHEMA_TYPE_ELEMENT:
4955 case XML_SCHEMA_TYPE_ATTRIBUTE:
4956 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4957 case XML_SCHEMA_TYPE_NOTATION:
4958 case XML_SCHEMA_TYPE_LIST:
William M. Bracke7091952004-05-11 15:09:58 +00004959 xmlSchemaParseListRefFixup(typeDecl, ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004960 case XML_SCHEMA_TYPE_UNION:
Daniel Veillard377e1a92004-04-16 16:30:05 +00004961 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004962 case XML_SCHEMA_FACET_MININCLUSIVE:
4963 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4964 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4965 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4966 case XML_SCHEMA_FACET_TOTALDIGITS:
4967 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4968 case XML_SCHEMA_FACET_PATTERN:
4969 case XML_SCHEMA_FACET_ENUMERATION:
4970 case XML_SCHEMA_FACET_WHITESPACE:
4971 case XML_SCHEMA_FACET_LENGTH:
4972 case XML_SCHEMA_FACET_MAXLENGTH:
4973 case XML_SCHEMA_FACET_MINLENGTH:
4974 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004975 if (typeDecl->subtypes != NULL)
4976 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004977 break;
4978 }
4979 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004980#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004981 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004982 xmlGenericError(xmlGenericErrorContext,
4983 "Type of %s : %s:%d :", name,
4984 typeDecl->node->doc->URL,
4985 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004986 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004987 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004988 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004989 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004990 case XML_SCHEMA_CONTENT_SIMPLE:
4991 xmlGenericError(xmlGenericErrorContext, "simple\n");
4992 break;
4993 case XML_SCHEMA_CONTENT_ELEMENTS:
4994 xmlGenericError(xmlGenericErrorContext, "elements\n");
4995 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004996 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004997 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
4998 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004999 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005000 xmlGenericError(xmlGenericErrorContext, "empty\n");
5001 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005002 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005003 xmlGenericError(xmlGenericErrorContext, "mixed\n");
5004 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005005 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005006 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
5007 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005008 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005009 xmlGenericError(xmlGenericErrorContext, "basic\n");
5010 break;
5011 default:
5012 xmlGenericError(xmlGenericErrorContext,
5013 "not registered !!!\n");
5014 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005015 }
5016#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00005017}
5018
5019/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005020 * xmlSchemaCheckFacet:
5021 * @facet: the facet
5022 * @typeDecl: the schema type definition
5023 * @ctxt: the schema parser context or NULL
5024 * @name: name of the type
5025 *
5026 * Checks the default values types, especially for facets
5027 *
5028 * Returns 0 if okay or -1 in cae of error
5029 */
5030int
5031xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005032 xmlSchemaTypePtr typeDecl,
5033 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005034{
5035 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
5036 int ret = 0;
5037
5038 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005039 nonNegativeIntegerType =
5040 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
5041 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005042 }
5043 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005044 case XML_SCHEMA_FACET_MININCLUSIVE:
5045 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5046 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5047 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
5048 /*
5049 * Okay we need to validate the value
5050 * at that point.
5051 */
5052 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005053
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005054 vctxt = xmlSchemaNewValidCtxt(NULL);
5055 if (vctxt == NULL)
5056 break;
5057 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
5058 facet->value);
5059 facet->val = vctxt->value;
5060 vctxt->value = NULL;
5061 if (facet->val == NULL) {
5062 /* error code */
5063 if (ctxt != NULL) {
5064 xmlSchemaPErr(ctxt, facet->node,
5065 XML_SCHEMAP_INVALID_FACET,
5066 "Schemas: type %s facet value %s invalid\n",
5067 name, facet->value);
5068 }
5069 ret = -1;
5070 }
5071 xmlSchemaFreeValidCtxt(vctxt);
5072 break;
5073 }
5074 case XML_SCHEMA_FACET_ENUMERATION:{
5075 /*
5076 * Okay we need to validate the value
5077 * at that point.
5078 */
5079 xmlSchemaValidCtxtPtr vctxt;
5080 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005081
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005082 vctxt = xmlSchemaNewValidCtxt(NULL);
5083 if (vctxt == NULL)
5084 break;
5085 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
5086 facet->value);
5087 if (tmp != 0) {
5088 if (ctxt != NULL) {
5089 xmlSchemaPErr(ctxt, facet->node,
5090 XML_SCHEMAP_INVALID_ENUM,
5091 "Schemas: type %s enumeration value %s invalid\n",
5092 name, facet->value);
5093 }
5094 ret = -1;
5095 }
5096 xmlSchemaFreeValidCtxt(vctxt);
5097 break;
5098 }
5099 case XML_SCHEMA_FACET_PATTERN:
5100 facet->regexp = xmlRegexpCompile(facet->value);
5101 if (facet->regexp == NULL) {
5102 xmlSchemaPErr(ctxt, typeDecl->node,
5103 XML_SCHEMAP_REGEXP_INVALID,
5104 "Schemas: type %s facet regexp %s invalid\n",
5105 name, facet->value);
5106 ret = -1;
5107 }
5108 break;
5109 case XML_SCHEMA_FACET_TOTALDIGITS:
5110 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5111 case XML_SCHEMA_FACET_LENGTH:
5112 case XML_SCHEMA_FACET_MAXLENGTH:
5113 case XML_SCHEMA_FACET_MINLENGTH:{
5114 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005115
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005116 tmp =
5117 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
5118 facet->value,
5119 &facet->val);
5120 if (tmp != 0) {
5121 /* error code */
5122 if (ctxt != NULL) {
5123 xmlSchemaPErr(ctxt, facet->node,
5124 XML_SCHEMAP_INVALID_FACET_VALUE,
5125 "Schemas: type %s facet value %s invalid\n",
5126 name, facet->value);
5127 }
5128 ret = -1;
5129 }
5130 break;
5131 }
5132 case XML_SCHEMA_FACET_WHITESPACE:{
5133 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
5134 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
5135 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
5136 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
5137 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
5138 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
5139 } else {
5140 if (ctxt != NULL) {
5141 xmlSchemaPErr(ctxt, facet->node,
5142 XML_SCHEMAP_INVALID_WHITE_SPACE,
5143 "Schemas: type %s whiteSpace value %s invalid\n",
5144 name, facet->value);
5145 }
5146 ret = -1;
5147 }
5148 }
5149 default:
5150 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005151 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005152 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005153}
5154
5155/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005156 * xmlSchemaCheckDefaults:
5157 * @typeDecl: the schema type definition
5158 * @ctxt: the schema parser context
5159 *
5160 * Checks the default values types, especially for facets
5161 */
5162static void
5163xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005164 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00005165{
Daniel Veillard4255d502002-04-16 15:50:10 +00005166 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005167 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005168 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005169 if (typeDecl->facets != NULL) {
5170 xmlSchemaFacetPtr facet = typeDecl->facets;
5171
5172 while (facet != NULL) {
5173 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
5174 facet = facet->next;
5175 }
5176 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005177 }
5178}
5179
5180/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00005181 * xmlSchemaAttrGrpFixup:
5182 * @attrgrpDecl: the schema attribute definition
5183 * @ctxt: the schema parser context
5184 * @name: the attribute name
5185 *
5186 * Fixes finish doing the computations on the attributes definitions
5187 */
5188static void
5189xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005190 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00005191{
5192 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005193 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005194 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005195 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005196 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005197 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005198
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005199 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
5200 attrgrpDecl->refNs);
5201 if (ref == NULL) {
5202 xmlSchemaPErr(ctxt, attrgrpDecl->node,
5203 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
5204 "Schemas: attribute group %s reference %s not found\n",
5205 name, attrgrpDecl->ref);
5206 return;
5207 }
5208 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
5209 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005210 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005211 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
5212 "Schemas: attribute %s has no attributes nor reference\n",
5213 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00005214 }
5215}
5216
5217/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005218 * xmlSchemaAttrFixup:
5219 * @attrDecl: the schema attribute definition
5220 * @ctxt: the schema parser context
5221 * @name: the attribute name
5222 *
5223 * Fixes finish doing the computations on the attributes definitions
5224 */
5225static void
5226xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005227 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00005228{
5229 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005230 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005231 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005232 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005233 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005234 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005235
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005236 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
5237 attrDecl->typeNs);
5238 if (type == NULL) {
5239 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
5240 "Schemas: attribute %s type %s not found\n",
5241 name, attrDecl->typeName);
5242 }
5243 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005244 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005245 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00005246
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005247 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
5248 attrDecl->refNs);
5249 if (ref == NULL) {
5250 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
5251 "Schemas: attribute %s reference %s not found\n",
5252 name, attrDecl->ref);
5253 return;
5254 }
5255 xmlSchemaAttrFixup(ref, ctxt, NULL);
5256 attrDecl->subtypes = ref->subtypes;
William M. Bracke7091952004-05-11 15:09:58 +00005257 } else if (attrDecl->type != XML_SCHEMA_TYPE_ANY_ATTRIBUTE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005258 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
5259 "Schemas: attribute %s has no type nor reference\n",
5260 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005261 }
5262}
5263
5264/**
5265 * xmlSchemaParse:
5266 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00005267 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00005268 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00005269 * XML Shema struture which can be used to validate instances.
5270 * *WARNING* this interface is highly subject to change
5271 *
5272 * Returns the internal XML Schema structure built from the resource or
5273 * NULL in case of error
5274 */
5275xmlSchemaPtr
5276xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
5277{
5278 xmlSchemaPtr ret = NULL;
5279 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005280 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005281 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005282 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005283
5284 xmlSchemaInitTypes();
5285
Daniel Veillard6045c902002-10-09 21:13:59 +00005286 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00005287 return (NULL);
5288
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005289 nberrors = ctxt->nberrors;
5290 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005291 ctxt->counter = 0;
5292 ctxt->container = NULL;
5293
5294 /*
5295 * First step is to parse the input document into an DOM/Infoset
5296 */
Daniel Veillard6045c902002-10-09 21:13:59 +00005297 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005298 doc = xmlReadFile((const char *) ctxt->URL, NULL,
5299 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005300 if (doc == NULL) {
5301 xmlSchemaPErr(ctxt, NULL,
5302 XML_SCHEMAP_FAILED_LOAD,
5303 "xmlSchemaParse: could not load %s\n",
5304 ctxt->URL, NULL);
5305 return (NULL);
5306 }
Daniel Veillard6045c902002-10-09 21:13:59 +00005307 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005308 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
5309 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005310 if (doc == NULL) {
5311 xmlSchemaPErr(ctxt, NULL,
5312 XML_SCHEMAP_FAILED_PARSE,
5313 "xmlSchemaParse: could not parse\n",
5314 NULL, NULL);
5315 return (NULL);
5316 }
5317 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00005318 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00005319 } else if (ctxt->doc != NULL) {
5320 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005321 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00005322 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005323 xmlSchemaPErr(ctxt, NULL,
5324 XML_SCHEMAP_NOTHING_TO_PARSE,
5325 "xmlSchemaParse: could not parse\n",
5326 NULL, NULL);
5327 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005328 }
5329
5330 /*
5331 * Then extract the root and Schema parse it
5332 */
5333 root = xmlDocGetRootElement(doc);
5334 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005335 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
5336 XML_SCHEMAP_NOROOT,
5337 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00005338 if (!preserve) {
5339 xmlFreeDoc(doc);
5340 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005341 return (NULL);
5342 }
5343
5344 /*
5345 * Remove all the blank text nodes
5346 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005347 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00005348
5349 /*
5350 * Then do the parsing for good
5351 */
5352 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00005353 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00005354 if (!preserve) {
5355 xmlFreeDoc(doc);
5356 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005357 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00005358 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005359 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005360 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00005361
5362 /*
5363 * Then fix all the references.
5364 */
5365 ctxt->schema = ret;
5366 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005367 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005368
5369 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005370 * Then fixup all attributes declarations
5371 */
5372 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
5373
5374 /*
5375 * Then fixup all attributes group declarations
5376 */
5377 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
5378 ctxt);
5379
5380 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00005381 * Then fixup all types properties
5382 */
5383 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
5384
5385 /*
5386 * Then build the content model for all elements
5387 */
5388 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005389 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005390
5391 /*
5392 * Then check the defaults part of the type like facets values
5393 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005394 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
5395 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005396
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005397 if (ctxt->nberrors != 0) {
5398 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005399 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005400 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005401 return (ret);
5402}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005403
Daniel Veillard4255d502002-04-16 15:50:10 +00005404/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00005405 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00005406 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00005407 * @err: the error callback
5408 * @warn: the warning callback
5409 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00005410 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00005411 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00005412 */
5413void
5414xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005415 xmlSchemaValidityErrorFunc err,
5416 xmlSchemaValidityWarningFunc warn, void *ctx)
5417{
Daniel Veillard4255d502002-04-16 15:50:10 +00005418 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005419 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005420 ctxt->error = err;
5421 ctxt->warning = warn;
5422 ctxt->userData = ctx;
5423}
5424
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005425/**
5426 * xmlSchemaFacetTypeToString:
5427 * @type: the facet type
5428 *
5429 * Convert the xmlSchemaTypeType to a char string.
5430 *
5431 * Returns the char string representation of the facet type if the
5432 * type is a facet and an "Internal Error" string otherwise.
5433 */
5434static const char *
5435xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5436{
5437 switch (type) {
5438 case XML_SCHEMA_FACET_PATTERN:
5439 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005440 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005441 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005442 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005443 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005444 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005445 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005446 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005447 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005448 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005449 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005450 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005451 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005452 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005453 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005454 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005455 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005456 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005457 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005458 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005459 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005460 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005461 return ("fractionDigits");
5462 default:
5463 break;
5464 }
5465 return ("Internal Error");
5466}
5467
5468/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00005469 * xmlSchemaValidateFacetsInternal:
5470 * @ctxt: a schema validation context
5471 * @base: the base type
5472 * @facets: the list of facets to check
5473 * @value: the lexical repr of the value to validate
5474 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +00005475 * @fireErrors: if 0, only internal errors will be fired;
5476 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00005477 *
5478 * Check a value against all facet conditions
5479 *
5480 * Returns 0 if the element is schemas valid, a positive error code
5481 * number otherwise and -1 in case of internal or API error.
5482 */
5483static int
5484xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
5485 xmlSchemaTypePtr base,
William M. Bracke7091952004-05-11 15:09:58 +00005486 xmlSchemaFacetPtr facets,
5487 const xmlChar * value, int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00005488{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005489 int ret = 0;
5490 int tmp = 0;
5491 xmlSchemaTypeType type;
5492 xmlSchemaFacetPtr facet = facets;
5493
5494 while (facet != NULL) {
5495 type = facet->type;
5496 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005497 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005498
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005499 while (facet != NULL) {
5500 tmp =
5501 xmlSchemaValidateFacet(base, facet, value,
5502 ctxt->value);
5503 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005504 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005505 }
5506 facet = facet->next;
5507 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005508 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005509 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005510
5511 if (tmp != 0) {
5512 ret = tmp;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005513 if (fireErrors)
William M. Bracke7091952004-05-11 15:09:58 +00005514 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET,
5515 "Failed to validate type with facet %s\n",
5516 (const xmlChar *) xmlSchemaFacetTypeToString(type),
5517 NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005518 }
5519 if (facet != NULL)
5520 facet = facet->next;
5521 }
5522 return (ret);
5523}
5524
William M. Brack87640d52004-04-17 14:58:15 +00005525/**
5526 * xmlSchemaValidateFacets:
5527 * @ctxt: a schema validation context
5528 * @base: the base type
5529 * @facets: the list of facets to check
5530 * @value: the lexical repr of the value to validate
5531 * @val: the precomputed value
5532 *
5533 * Check a value against all facet conditions
5534 *
5535 * Returns 0 if the element is schemas valid, a positive error code
5536 * number otherwise and -1 in case of internal or API error.
5537 */
5538static int
5539xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5540 xmlSchemaTypePtr base,
5541 xmlSchemaFacetPtr facets, const xmlChar * value)
5542{
5543 return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
5544}
5545
Daniel Veillard4255d502002-04-16 15:50:10 +00005546/************************************************************************
5547 * *
5548 * Simple type validation *
5549 * *
5550 ************************************************************************/
5551
5552/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00005553 * xmlSchemaValidateSimpleValueUnion:
5554 * @ctxt: a schema validation context
5555 * @type: the type declaration
5556 * @value: the value to validate
5557 *
5558 * Validates a value against a union.
5559 *
5560 * Returns 0 if the value is valid, a positive error code
5561 * number otherwise and -1 in case of internal or API error.
5562 */
5563static int
5564xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
5565 xmlSchemaTypePtr type, const xmlChar * value)
5566{
5567 int ret = 0;
5568 const xmlChar *cur, *end, *prefix, *ncName;
5569 xmlChar *tmp;
5570 xmlSchemaTypePtr subtype;
5571 xmlNsPtr ns;
5572 int len;
5573
5574
5575 /* Process referenced memberTypes. */
5576 cur = type->ref;
5577 do {
5578 while (IS_BLANK_CH(*cur))
5579 cur++;
5580 end = cur;
5581 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5582 end++;
5583 if (end == cur)
5584 break;
5585 tmp = xmlStrndup(cur, end - cur);
5586 ncName = xmlSplitQName3(tmp, &len);
5587 if (ncName != NULL) {
5588 prefix = xmlStrndup(tmp, len);
5589 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
5590 } else {
5591 prefix = NULL;
5592 ncName = tmp;
5593 }
William M. Bracke7091952004-05-11 15:09:58 +00005594 /* We won't do additional checks here,
5595 * since they have been performed during parsing. */
Daniel Veillard377e1a92004-04-16 16:30:05 +00005596 ns = xmlSearchNs(type->node->doc, type->node, prefix);
5597 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
5598 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
5599 if (tmp != NULL)
5600 xmlFree(tmp);
5601 if (prefix != NULL)
William M. Brack87640d52004-04-17 14:58:15 +00005602 xmlFree((void *)prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005603 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5604 if ((ret == 0) || (ret == -1)) {
5605 return (ret);
5606 }
5607 cur = end;
5608 } while (*cur != 0);
5609
5610 if (type->subtypes != NULL) {
5611 subtype = type->subtypes;
5612 do {
5613 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5614 if ((ret == 0) || (ret == -1)) {
5615 return (ret);
5616 }
5617 subtype = subtype->next;
5618 } while (subtype != NULL);
5619 }
5620 return (ret);
5621}
5622
5623/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005624 * xmlSchemaValidateSimpleValue:
5625 * @ctxt: a schema validation context
5626 * @type: the type declaration
5627 * @value: the value to validate
5628 *
5629 * Validate a value against a simple type
5630 *
5631 * Returns 0 if the value is valid, a positive error code
5632 * number otherwise and -1 in case of internal or API error.
5633 */
5634static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005635xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005636 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005637{
Daniel Veillard377e1a92004-04-16 16:30:05 +00005638 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
5639}
5640
5641/**
5642 * xmlSchemaValidateSimpleValue:
5643 * @ctxt: a schema validation context
5644 * @type: the type declaration
5645 * @value: the value to validate
William M. Bracke7091952004-05-11 15:09:58 +00005646 * @fireErrors: if 0, only internal errors will be fired;
5647 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00005648 *
5649 * Validate a value against a simple type
5650 *
5651 * Returns 0 if the value is valid, a positive error code
5652 * number otherwise and -1 in case of internal or API error.
5653 */
5654static int
5655xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
William M. Bracke7091952004-05-11 15:09:58 +00005656 xmlSchemaTypePtr type,
5657 const xmlChar * value,
5658 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00005659{
Daniel Veillard4255d502002-04-16 15:50:10 +00005660 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005661
Daniel Veillard4255d502002-04-16 15:50:10 +00005662 /*
5663 * First normalize the value accordingly to Schema Datatype
5664 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
William M. Bracke7091952004-05-11 15:09:58 +00005665 *
Daniel Veillard4255d502002-04-16 15:50:10 +00005666 * Then check the normalized value against the lexical space of the
5667 * type.
5668 */
5669 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005670 if (ctxt->value != NULL) {
5671 xmlSchemaFreeValue(ctxt->value);
5672 ctxt->value = NULL;
5673 }
5674 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5675 ctxt->cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005676 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00005677 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
5678 "Failed to validate basic type %s\n",
5679 type->name, NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005680 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005681 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005682 xmlSchemaTypePtr base;
5683 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005684
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005685 base = type->baseType;
5686 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005687 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5688 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005689 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005690 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005691 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005692
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005693 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005694 * Do not validate facets or attributes when working on
5695 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005696 */
5697 if (ctxt->schema != NULL) {
5698 if (ret == 0) {
5699 facet = type->facets;
William M. Bracke7091952004-05-11 15:09:58 +00005700 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet,
5701 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005702 }
5703 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005704 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005705 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00005706
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005707 base = type->subtypes;
5708 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005709 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5710 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005711 } else {
5712 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00005713 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005714 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005715 const xmlChar *cur, *end;
5716 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005717 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00005718
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005719 base = type->subtypes;
5720 if (base == NULL) {
5721 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5722 "Internal: List type %s has no base type\n",
5723 type->name, NULL);
5724 return (-1);
5725 }
5726 cur = value;
5727 do {
William M. Brack76e95df2003-10-18 16:20:14 +00005728 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005729 cur++;
5730 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00005731 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005732 end++;
5733 if (end == cur)
5734 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005735 tmp = xmlStrndup(cur, end - cur);
William M. Bracke7091952004-05-11 15:09:58 +00005736 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5737 tmp, fireErrors);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005738 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005739 if (ret2 != 0)
5740 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005741 cur = end;
5742 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005743 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
5744 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
5745 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00005746 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
5747 "Failed to validate type %s\n", type->name, NULL);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005748 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005749 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005750 TODO
5751 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005752 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005753}
5754
5755/************************************************************************
5756 * *
5757 * DOM Validation code *
5758 * *
5759 ************************************************************************/
5760
5761static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005762 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005763static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005764 xmlNodePtr elem,
5765 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005766static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005767 xmlNodePtr elem,
5768 xmlSchemaElementPtr elemDecl,
5769 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00005770
5771/**
5772 * xmlSchemaRegisterAttributes:
5773 * @ctxt: a schema validation context
5774 * @attrs: a list of attributes
5775 *
5776 * Register the list of attributes as the set to be validated on that element
5777 *
5778 * Returns -1 in case of error, 0 otherwise
5779 */
5780static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005781xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5782{
Daniel Veillard4255d502002-04-16 15:50:10 +00005783 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005784 if ((attrs->ns != NULL) &&
5785 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5786 attrs = attrs->next;
5787 continue;
5788 }
5789 if (ctxt->attrNr >= ctxt->attrMax) {
5790 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00005791
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005792 ctxt->attrMax *= 2;
5793 tmp = (xmlSchemaAttrStatePtr)
5794 xmlRealloc(ctxt->attr, ctxt->attrMax *
5795 sizeof(xmlSchemaAttrState));
5796 if (tmp == NULL) {
5797 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5798 ctxt->attrMax /= 2;
5799 return (-1);
5800 }
5801 ctxt->attr = tmp;
5802 }
5803 ctxt->attr[ctxt->attrNr].attr = attrs;
5804 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5805 ctxt->attrNr++;
5806 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005807 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005809}
5810
5811/**
5812 * xmlSchemaCheckAttributes:
5813 * @ctxt: a schema validation context
5814 * @node: the node carrying it.
5815 *
5816 * Check that the registered set of attributes on the current node
5817 * has been properly validated.
5818 *
5819 * Returns 0 if validity constraints are met, 1 otherwise.
5820 */
5821static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005822xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5823{
Daniel Veillard4255d502002-04-16 15:50:10 +00005824 int ret = 0;
5825 int i;
5826
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005827 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5828 if (ctxt->attr[i].attr == NULL)
5829 break;
5830 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5831 ret = 1;
William M. Bracke7091952004-05-11 15:09:58 +00005832 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
5833 "Attribute %s on %s is unknown\n",
5834 ctxt->attr[i].attr->name, node->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005835 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005836 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005837 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005838}
5839
5840/**
5841 * xmlSchemaValidateSimpleContent:
5842 * @ctxt: a schema validation context
5843 * @elem: an element
5844 * @type: the type declaration
5845 *
5846 * Validate the content of an element expected to be a simple type
5847 *
5848 * Returns 0 if the element is schemas valid, a positive error code
5849 * number otherwise and -1 in case of internal or API error.
5850 */
5851static int
5852xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005853 xmlNodePtr node ATTRIBUTE_UNUSED)
5854{
Daniel Veillard4255d502002-04-16 15:50:10 +00005855 xmlNodePtr child;
5856 xmlSchemaTypePtr type, base;
5857 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005858 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005859
5860 child = ctxt->node;
5861 type = ctxt->type;
5862
5863 /*
5864 * Validation Rule: Element Locally Valid (Type): 3.1.3
5865 */
5866 value = xmlNodeGetContent(child);
5867 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5868 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005869 case XML_SCHEMA_TYPE_RESTRICTION:{
5870 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005871
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005872 base = type->baseType;
5873 if (base != NULL) {
5874 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5875 } else {
5876 TODO}
5877 if (ret == 0) {
5878 facet = type->facets;
5879 ret =
5880 xmlSchemaValidateFacets(ctxt, base, facet, value);
5881 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005882 if ((ret == 0) && (type->attributes != NULL)) {
5883 ret = xmlSchemaValidateAttributes(ctxt, node,
5884 type->attributes);
5885 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005886 break;
5887 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005888 case XML_SCHEMA_TYPE_EXTENSION:{
5889 TODO
5890 break;
5891 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005892 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005893 TODO
5894 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005895 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005896 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005897
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005898 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005899}
5900
5901/**
5902 * xmlSchemaValidateCheckNodeList
5903 * @nodelist: the list of nodes
5904 *
5905 * Check the node list is only made of text nodes and entities pointing
5906 * to text nodes
5907 *
5908 * Returns 1 if true, 0 if false and -1 in case of error
5909 */
5910static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005911xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5912{
Daniel Veillard4255d502002-04-16 15:50:10 +00005913 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005914 if (nodelist->type == XML_ENTITY_REF_NODE) {
5915 TODO /* implement recursion in the entity content */
5916 }
5917 if ((nodelist->type != XML_TEXT_NODE) &&
5918 (nodelist->type != XML_COMMENT_NODE) &&
5919 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +00005920 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005921 return (0);
5922 }
5923 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005924 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005925 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005926}
5927
5928/**
5929 * xmlSchemaSkipIgnored:
5930 * @ctxt: a schema validation context
5931 * @type: the current type context
5932 * @node: the top node.
5933 *
5934 * Skip ignorable nodes in that context
5935 *
5936 * Returns the new sibling
5937 * number otherwise and -1 in case of internal or API error.
5938 */
5939static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005940xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005941 xmlSchemaTypePtr type, xmlNodePtr node)
5942{
Daniel Veillard4255d502002-04-16 15:50:10 +00005943 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005944
Daniel Veillard4255d502002-04-16 15:50:10 +00005945 /*
5946 * TODO complete and handle entities
5947 */
5948 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005949 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005950 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005951 ((node->type == XML_COMMENT_NODE) ||
5952 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5953 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5954 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5955 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005956 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005957 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005958}
5959
5960/**
5961 * xmlSchemaValidateCallback:
5962 * @ctxt: a schema validation context
5963 * @name: the name of the element detected (might be NULL)
5964 * @type: the type
5965 *
5966 * A transition has been made in the automata associated to an element
5967 * content model
5968 */
5969static void
5970xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005971 const xmlChar * name ATTRIBUTE_UNUSED,
5972 xmlSchemaTypePtr type, xmlNodePtr node)
5973{
Daniel Veillard4255d502002-04-16 15:50:10 +00005974 xmlSchemaTypePtr oldtype = ctxt->type;
5975 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005976
Daniel Veillard4255d502002-04-16 15:50:10 +00005977#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00005978 xmlGenericError(xmlGenericErrorContext,
5979 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005980 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005981#endif
5982 ctxt->type = type;
5983 ctxt->node = node;
5984 xmlSchemaValidateContent(ctxt, node);
5985 ctxt->type = oldtype;
5986 ctxt->node = oldnode;
5987}
5988
5989
5990#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005991
Daniel Veillard4255d502002-04-16 15:50:10 +00005992/**
5993 * xmlSchemaValidateSimpleRestrictionType:
5994 * @ctxt: a schema validation context
5995 * @node: the top node.
5996 *
5997 * Validate the content of a restriction type.
5998 *
5999 * Returns 0 if the element is schemas valid, a positive error code
6000 * number otherwise and -1 in case of internal or API error.
6001 */
6002static int
6003xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
6004 xmlNodePtr node)
6005{
6006 xmlNodePtr child;
6007 xmlSchemaTypePtr type;
6008 int ret;
6009
6010 child = ctxt->node;
6011 type = ctxt->type;
6012
6013 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006014 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6015 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
6016 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006017 return (-1);
6018 }
6019 /*
6020 * Only text and text based entities references shall be found there
6021 */
6022 ret = xmlSchemaValidateCheckNodeList(child);
6023 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006024 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6025 "Internal error: xmlSchemaValidateSimpleType %s content\n",
6026 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006027 return (-1);
6028 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006029 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
6030 "Element %s content is not a simple type\n",
6031 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006032 return (-1);
6033 }
6034 ctxt->type = type->subtypes;
6035 xmlSchemaValidateContent(ctxt, node);
6036 ctxt->type = type;
6037 return (ret);
6038}
6039#endif
6040
6041/**
6042 * xmlSchemaValidateSimpleType:
6043 * @ctxt: a schema validation context
6044 * @node: the top node.
6045 *
6046 * Validate the content of an simple type.
6047 *
6048 * Returns 0 if the element is schemas valid, a positive error code
6049 * number otherwise and -1 in case of internal or API error.
6050 */
6051static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006052xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6053{
Daniel Veillard4255d502002-04-16 15:50:10 +00006054 xmlNodePtr child;
William M. Bracke7091952004-05-11 15:09:58 +00006055 xmlSchemaTypePtr type, base, variety;
Daniel Veillard4255d502002-04-16 15:50:10 +00006056 xmlAttrPtr attr;
6057 int ret;
William M. Bracke7091952004-05-11 15:09:58 +00006058 xmlChar *value;
6059
Daniel Veillard4255d502002-04-16 15:50:10 +00006060
6061 child = ctxt->node;
6062 type = ctxt->type;
6063
6064 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006065 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6066 "Internal error: xmlSchemaValidateSimpleType %s\n",
6067 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006068 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006069 }
6070 /*
6071 * Only text and text based entities references shall be found there
6072 */
6073 ret = xmlSchemaValidateCheckNodeList(child);
6074 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006075 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6076 "Internal error: xmlSchemaValidateSimpleType %s content\n",
6077 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006078 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006079 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006080 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
6081 "Element %s content is not a simple type\n",
6082 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006083 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006084 }
6085 /*
6086 * Validation Rule: Element Locally Valid (Type): 3.1.1
William M. Bracke7091952004-05-11 15:09:58 +00006087 */
6088
Daniel Veillard4255d502002-04-16 15:50:10 +00006089 attr = node->properties;
6090 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006091 if ((attr->ns == NULL) ||
6092 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
6093 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6094 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
6095 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
6096 (!xmlStrEqual
6097 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
William M. Bracke7091952004-05-11 15:09:58 +00006098 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
6099 "Element %s: attribute %s should not be present\n",
6100 node->name, attr->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006101 return (ctxt->err);
6102 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006103 }
William M. Bracke7091952004-05-11 15:09:58 +00006104 /* TODO:
6105 * If {variety} is ·atomic· then the {variety} of {base type definition}
6106 * must be ·atomic·.
6107 * If {variety} is ·list· then the {variety} of {item type definition}
6108 * must be either ·atomic· or ·union·.
6109 * If {variety} is ·union· then {member type definitions} must be a list
6110 * of datatype definitions.
6111 */
6112 if (type->subtypes == NULL) {
6113 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6114 "Internal error: xmlSchemaValidateSimpleType; "
6115 "simple type %s does not define a variety\n",
6116 node->name, NULL);
6117 return (ctxt->err);
6118 }
6119 /* Varieties: Restriction or List or Union. */
6120 variety = type->subtypes;
6121 ctxt->type = variety;
6122 value = xmlNodeGetContent(child);
6123 switch (variety->type) {
6124 case XML_SCHEMA_TYPE_RESTRICTION:{
6125 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00006126
William M. Bracke7091952004-05-11 15:09:58 +00006127 base = variety->baseType;
6128 if (base != NULL) {
6129 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
6130 } else {
6131 TODO}
6132 if (ret == 0) {
6133 facet = variety->facets;
6134 ret =
6135 xmlSchemaValidateFacets(ctxt, base, facet, value);
6136 }
6137 if ((ret == 0) && (variety->attributes != NULL)) {
6138 ret = xmlSchemaValidateAttributes(ctxt, node,
6139 variety->attributes);
6140 }
6141 break;
6142 }
6143 case XML_SCHEMA_TYPE_LIST:
6144 case XML_SCHEMA_TYPE_UNION: {
6145 ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
6146 break;
6147 }
6148 default:{
6149 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6150 "Internal error: xmlSchemaValidateSimpleType; "
6151 "simple type %s defines unknown content: %s\n",
6152 variety->name, NULL);
6153 ret = ctxt->err;
6154 }
6155 }
6156 if (value != NULL)
6157 xmlFree(value);
6158
6159 /* This was removed, since a simple content is not a content of a
6160 * simple type, but of a complex type.
6161 * ret = xmlSchemaValidateSimpleContent(ctxt, node);
6162 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006163 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006164 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006165}
6166
6167/**
6168 * xmlSchemaValidateElementType:
6169 * @ctxt: a schema validation context
6170 * @node: the top node.
6171 *
6172 * Validate the content of an element type.
6173 * Validation Rule: Element Locally Valid (Complex Type)
6174 *
6175 * Returns 0 if the element is schemas valid, a positive error code
6176 * number otherwise and -1 in case of internal or API error.
6177 */
6178static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006179xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6180{
Daniel Veillard4255d502002-04-16 15:50:10 +00006181 xmlNodePtr child;
6182 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006183 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00006184 xmlSchemaElementPtr decl;
6185 int ret, attrBase;
6186
6187 oldregexp = ctxt->regexp;
6188
6189 child = ctxt->node;
6190 type = ctxt->type;
6191
6192 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006193 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6194 "Internal error: xmlSchemaValidateElementType\n",
6195 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006196 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006197 }
6198 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006199 if (type->minOccurs > 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006200 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
6201 "Element %s: missing child %s\n",
6202 node->name, type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006203 }
6204 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006205 }
6206
6207 /*
6208 * Verify the element matches
6209 */
6210 if (!xmlStrEqual(child->name, type->name)) {
William M. Bracke7091952004-05-11 15:09:58 +00006211 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
6212 "Element %s: missing child %s found %s\n",
6213 node->name, type->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006214 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006215 }
6216 /*
6217 * Verify the attributes
6218 */
6219 attrBase = ctxt->attrBase;
6220 ctxt->attrBase = ctxt->attrNr;
6221 xmlSchemaRegisterAttributes(ctxt, child->properties);
6222 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
6223 /*
6224 * Verify the element content recursively
6225 */
6226 decl = (xmlSchemaElementPtr) type;
6227 oldregexp = ctxt->regexp;
6228 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006229 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
6230 (xmlRegExecCallbacks)
6231 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006232#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006233 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006234#endif
6235 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006236 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
6237 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00006238
6239 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006240 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006241#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006242 xmlGenericError(xmlGenericErrorContext,
6243 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006244#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006245 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006246 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
6247 "Element %s content check failed\n",
6248 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006249 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006250 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
6251 "Element %s content check failure\n",
6252 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006253#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006254 } else {
6255 xmlGenericError(xmlGenericErrorContext,
6256 "Element %s content check succeeded\n",
6257 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006258
6259#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006260 }
6261 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006262 }
6263 /*
6264 * Verify that all attributes were Schemas-validated
6265 */
6266 xmlSchemaCheckAttributes(ctxt, node);
6267 ctxt->attrNr = ctxt->attrBase;
6268 ctxt->attrBase = attrBase;
6269
6270 ctxt->regexp = oldregexp;
6271
6272 ctxt->node = child;
6273 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006274 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006275}
6276
6277/**
6278 * xmlSchemaValidateBasicType:
6279 * @ctxt: a schema validation context
6280 * @node: the top node.
6281 *
6282 * Validate the content of an element expected to be a basic type type
6283 *
6284 * Returns 0 if the element is schemas valid, a positive error code
6285 * number otherwise and -1 in case of internal or API error.
6286 */
6287static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006288xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6289{
Daniel Veillard4255d502002-04-16 15:50:10 +00006290 int ret;
6291 xmlNodePtr child, cur;
6292 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006293 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00006294
6295 child = ctxt->node;
6296 type = ctxt->type;
6297
6298 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006299 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6300 "Internal error: xmlSchemaValidateBasicType\n",
6301 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006302 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006303 }
6304 /*
6305 * First check the content model of the node.
6306 */
6307 cur = child;
6308 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006309 switch (cur->type) {
6310 case XML_TEXT_NODE:
6311 case XML_CDATA_SECTION_NODE:
6312 case XML_PI_NODE:
6313 case XML_COMMENT_NODE:
6314 case XML_XINCLUDE_START:
6315 case XML_XINCLUDE_END:
6316 break;
6317 case XML_ENTITY_REF_NODE:
6318 case XML_ENTITY_NODE:
6319 TODO break;
6320 case XML_ELEMENT_NODE:
William M. Bracke7091952004-05-11 15:09:58 +00006321 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
6322 "Element %s: child %s should not be present\n",
6323 node->name, cur->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006324 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006325 case XML_ATTRIBUTE_NODE:
6326 case XML_DOCUMENT_NODE:
6327 case XML_DOCUMENT_TYPE_NODE:
6328 case XML_DOCUMENT_FRAG_NODE:
6329 case XML_NOTATION_NODE:
6330 case XML_HTML_DOCUMENT_NODE:
6331 case XML_DTD_NODE:
6332 case XML_ELEMENT_DECL:
6333 case XML_ATTRIBUTE_DECL:
6334 case XML_ENTITY_DECL:
6335 case XML_NAMESPACE_DECL:
6336#ifdef LIBXML_DOCB_ENABLED
6337 case XML_DOCB_DOCUMENT_NODE:
6338#endif
William M. Bracke7091952004-05-11 15:09:58 +00006339 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
6340 "Element %s: node type of node unexpected here\n",
6341 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006342 return (ctxt->err);
6343 }
6344 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006345 }
6346 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006347 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006348 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006349 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00006350
6351 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006352 xmlSchemaFreeValue(ctxt->value);
6353 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006354 }
6355 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
6356 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006357 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00006358 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006359 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
6360 "Element %s: failed to validate basic type %s\n",
6361 node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006362 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006363 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006364}
6365
6366/**
6367 * xmlSchemaValidateComplexType:
6368 * @ctxt: a schema validation context
6369 * @node: the top node.
6370 *
6371 * Validate the content of an element expected to be a complex type type
6372 * xmlschema-1.html#cvc-complex-type
6373 * Validation Rule: Element Locally Valid (Complex Type)
6374 *
6375 * Returns 0 if the element is schemas valid, a positive error code
6376 * number otherwise and -1 in case of internal or API error.
6377 */
6378static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006379xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6380{
Daniel Veillard4255d502002-04-16 15:50:10 +00006381 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00006382 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006383 int ret;
6384
6385 child = ctxt->node;
6386 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006387 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00006388
Daniel Veillard4255d502002-04-16 15:50:10 +00006389 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006390 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006391 if (type->baseType != NULL) {
6392 } else if (child != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006393 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY,
6394 "Element %s is supposed to be empty\n",
6395 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006396 }
6397 if (type->attributes != NULL) {
6398 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6399 }
6400 subtype = type->subtypes;
6401 while (subtype != NULL) {
6402 ctxt->type = subtype;
6403 xmlSchemaValidateComplexType(ctxt, node);
6404 subtype = subtype->next;
6405 }
6406 break;
6407 case XML_SCHEMA_CONTENT_ELEMENTS:
6408 case XML_SCHEMA_CONTENT_MIXED:
6409 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
6410 /*
6411 * Skip ignorable nodes in that context
6412 */
6413 child = xmlSchemaSkipIgnored(ctxt, type, child);
6414 while (child != NULL) {
6415 if (child->type == XML_ELEMENT_NODE) {
6416 ret = xmlRegExecPushString(ctxt->regexp,
6417 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00006418#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006419 if (ret < 0)
6420 xmlGenericError(xmlGenericErrorContext,
6421 " --> %s Error\n", child->name);
6422 else
6423 xmlGenericError(xmlGenericErrorContext,
6424 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006425#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006426 }
6427 child = child->next;
6428 /*
6429 * Skip ignorable nodes in that context
6430 */
6431 child = xmlSchemaSkipIgnored(ctxt, type, child);
6432 }
William M. Bracke7091952004-05-11 15:09:58 +00006433 if (((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
6434 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS)) &&
6435 (type->subtypes != NULL)) {
6436 TODO
6437 }
6438
6439
Daniel Veillardf2a12832003-11-24 13:04:35 +00006440 if (type->attributes != NULL) {
6441 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6442 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006443 break;
6444 case XML_SCHEMA_CONTENT_BASIC:{
6445 if (type->subtypes != NULL) {
6446 ctxt->type = type->subtypes;
6447 xmlSchemaValidateComplexType(ctxt, node);
6448 }
6449 if (type->baseType != NULL) {
6450 ctxt->type = type->baseType;
William M. Bracke7091952004-05-11 15:09:58 +00006451 if (type->baseType->type == XML_SCHEMA_TYPE_BASIC)
6452 xmlSchemaValidateBasicType(ctxt, node);
6453 else if (type->baseType->type == XML_SCHEMA_TYPE_COMPLEX)
6454 xmlSchemaValidateComplexType(ctxt, node);
6455 else if (type->baseType->type == XML_SCHEMA_TYPE_SIMPLE)
6456 xmlSchemaValidateSimpleType(ctxt, node);
6457 else
6458 xmlGenericError(xmlGenericErrorContext,
6459 "unexpected content type of base: %d\n",
6460 type->contentType);
6461
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006462 }
6463 if (type->attributes != NULL) {
6464 xmlSchemaValidateAttributes(ctxt, node,
6465 type->attributes);
6466 }
6467 ctxt->type = type;
6468 break;
6469 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006470 case XML_SCHEMA_CONTENT_SIMPLE:{
6471 if (type->subtypes != NULL) {
6472 ctxt->type = type->subtypes;
6473 xmlSchemaValidateComplexType(ctxt, node);
6474 }
6475 if (type->baseType != NULL) {
6476 ctxt->type = type->baseType;
6477 xmlSchemaValidateComplexType(ctxt, node);
6478 }
6479 if (type->attributes != NULL) {
6480 xmlSchemaValidateAttributes(ctxt, node,
6481 type->attributes);
6482 }
6483 ctxt->type = type;
6484 break;
6485 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006486 default:
6487 TODO xmlGenericError(xmlGenericErrorContext,
6488 "unimplemented content type %d\n",
6489 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006490 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006491 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006492}
6493
6494/**
6495 * xmlSchemaValidateContent:
6496 * @ctxt: a schema validation context
6497 * @elem: an element
6498 * @type: the type declaration
6499 *
6500 * Validate the content of an element against the type.
6501 *
6502 * Returns 0 if the element is schemas valid, a positive error code
6503 * number otherwise and -1 in case of internal or API error.
6504 */
6505static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006506xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6507{
Daniel Veillard4255d502002-04-16 15:50:10 +00006508 xmlNodePtr child;
6509 xmlSchemaTypePtr type;
6510
6511 child = ctxt->node;
6512 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006513 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00006514
Daniel Veillarde19fc232002-04-22 16:01:24 +00006515 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006516 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00006517
Daniel Veillard4255d502002-04-16 15:50:10 +00006518 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006519 case XML_SCHEMA_TYPE_ANY:
6520 /* Any type will do it, fine */
6521 TODO /* handle recursivity */
6522 break;
6523 case XML_SCHEMA_TYPE_COMPLEX:
6524 xmlSchemaValidateComplexType(ctxt, node);
6525 break;
6526 case XML_SCHEMA_TYPE_ELEMENT:{
6527 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
6528
6529 /*
6530 * Handle element reference here
6531 */
6532 if (decl->ref != NULL) {
6533 if (decl->refDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006534 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6535 "Internal error: element reference %s "
6536 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006537 return (-1);
6538 }
6539 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
6540 decl = decl->refDecl;
6541 }
William M. Bracke7091952004-05-11 15:09:58 +00006542 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006543 xmlSchemaValidateElementType(ctxt, node);
6544 ctxt->type = type;
6545 break;
6546 }
6547 case XML_SCHEMA_TYPE_BASIC:
6548 xmlSchemaValidateBasicType(ctxt, node);
6549 break;
6550 case XML_SCHEMA_TYPE_FACET:
6551 TODO break;
6552 case XML_SCHEMA_TYPE_SIMPLE:
6553 xmlSchemaValidateSimpleType(ctxt, node);
6554 break;
6555 case XML_SCHEMA_TYPE_SEQUENCE:
6556 TODO break;
6557 case XML_SCHEMA_TYPE_CHOICE:
6558 TODO break;
6559 case XML_SCHEMA_TYPE_ALL:
6560 TODO break;
6561 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
6562 TODO break;
6563 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
6564 TODO break;
6565 case XML_SCHEMA_TYPE_UR:
6566 TODO break;
6567 case XML_SCHEMA_TYPE_RESTRICTION:
6568 /*xmlSchemaValidateRestrictionType(ctxt, node); */
6569 TODO break;
6570 case XML_SCHEMA_TYPE_EXTENSION:
6571 TODO break;
6572 case XML_SCHEMA_TYPE_ATTRIBUTE:
6573 TODO break;
6574 case XML_SCHEMA_TYPE_GROUP:
6575 TODO break;
6576 case XML_SCHEMA_TYPE_NOTATION:
6577 TODO break;
6578 case XML_SCHEMA_TYPE_LIST:
6579 TODO break;
6580 case XML_SCHEMA_TYPE_UNION:
6581 TODO break;
6582 case XML_SCHEMA_FACET_MININCLUSIVE:
6583 TODO break;
6584 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6585 TODO break;
6586 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6587 TODO break;
6588 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
6589 TODO break;
6590 case XML_SCHEMA_FACET_TOTALDIGITS:
6591 TODO break;
6592 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6593 TODO break;
6594 case XML_SCHEMA_FACET_PATTERN:
6595 TODO break;
6596 case XML_SCHEMA_FACET_ENUMERATION:
6597 TODO break;
6598 case XML_SCHEMA_FACET_WHITESPACE:
6599 TODO break;
6600 case XML_SCHEMA_FACET_LENGTH:
6601 TODO break;
6602 case XML_SCHEMA_FACET_MAXLENGTH:
6603 TODO break;
6604 case XML_SCHEMA_FACET_MINLENGTH:
6605 TODO break;
6606 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
6607 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00006608 }
6609 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6610
6611 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006612 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006613 ctxt->node = ctxt->node->next;
6614 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006615 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006616}
6617
6618/**
6619 * xmlSchemaValidateType:
6620 * @ctxt: a schema validation context
6621 * @elem: an element
6622 * @type: the list of type declarations
6623 *
6624 * Validate the content of an element against the types.
6625 *
6626 * Returns 0 if the element is schemas valid, a positive error code
6627 * number otherwise and -1 in case of internal or API error.
6628 */
6629static int
6630xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006631 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
6632{
Daniel Veillard4255d502002-04-16 15:50:10 +00006633 xmlChar *nil;
6634
Daniel Veillard2db8c122003-07-08 12:16:59 +00006635 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006636 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00006637
Daniel Veillard4255d502002-04-16 15:50:10 +00006638 /*
6639 * 3.3.4 : 2
6640 */
6641 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
William M. Bracke7091952004-05-11 15:09:58 +00006642 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
6643 "Element declaration %s is abstract\n",
6644 elemDecl->name, NULL);
6645 /* Changed, since the element declaration is abstract and not
6646 * the element itself. */
6647 /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
6648 "Element %s is abstract\n", elem->name, NULL); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006649 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006650 }
6651 /*
6652 * 3.3.4: 3
6653 */
6654 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
6655 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006656 /* 3.3.4: 3.2 */
6657 if (xmlStrEqual(nil, BAD_CAST "true")) {
6658 if (elem->children != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006659 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
6660 "Element %s is not empty\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006661 return (ctxt->err);
6662 }
6663 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
6664 (elemDecl->value != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006665 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
6666 "Empty element %s cannot get a fixed value\n",
6667 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006668 return (ctxt->err);
6669 }
6670 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006671 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006672 /* 3.3.4: 3.1 */
6673 if (nil != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006674 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
6675 "Element %s with xs:nil but not nillable\n",
6676 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006677 xmlFree(nil);
6678 return (ctxt->err);
6679 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006680 }
6681
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006682 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00006683
6684 ctxt->type = elemDecl->subtypes;
6685 ctxt->node = elem->children;
6686 xmlSchemaValidateContent(ctxt, elem);
6687 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006688
6689 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006690}
6691
6692
6693/**
6694 * xmlSchemaValidateAttributes:
6695 * @ctxt: a schema validation context
6696 * @elem: an element
6697 * @attributes: the list of attribute declarations
6698 *
6699 * Validate the attributes of an element.
6700 *
6701 * Returns 0 if the element is schemas valid, a positive error code
6702 * number otherwise and -1 in case of internal or API error.
6703 */
6704static int
6705xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006706 xmlSchemaAttributePtr attributes)
6707{
William M. Brack87640d52004-04-17 14:58:15 +00006708 int i, ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006709 xmlAttrPtr attr;
6710 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006711 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006712 int found;
Daniel Veillard4255d502002-04-16 15:50:10 +00006713
6714 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006715 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006716 while (attributes != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006717 found = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006718 /*
6719 * Handle attribute groups
6720 */
6721 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6722 group = (xmlSchemaAttributeGroupPtr) attributes;
6723 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6724 attributes = group->next;
6725 continue;
6726 }
6727 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6728 attr = ctxt->attr[i].attr;
6729 if (attr == NULL)
6730 continue;
6731 if (attributes->ref != NULL) {
6732 if (!xmlStrEqual(attr->name, attributes->ref))
6733 continue;
6734 if (attr->ns != NULL) {
6735 if ((attributes->refNs == NULL) ||
6736 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6737 continue;
6738 } else if (attributes->refNs != NULL) {
6739 continue;
6740 }
6741 } else {
6742 if (!xmlStrEqual(attr->name, attributes->name))
6743 continue;
6744 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006745 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006746 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006747 if (attr->ns == NULL) {
6748 /*
William M. Bracke7091952004-05-11 15:09:58 +00006749 * accept an unqualified attribute only if the target
6750 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006751 */
William M. Bracke7091952004-05-11 15:09:58 +00006752 if (attributes->targetNamespace != NULL)
6753 /*
6754 * This check was removed, since the target namespace
6755 * was evaluated during parsing and already took
6756 * "attributeFormDefault" into account.
6757 */
6758 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006759 continue;
6760 } else {
6761 if (attributes->targetNamespace == NULL)
6762 continue;
6763 if (!xmlStrEqual(attributes->targetNamespace,
6764 attr->ns->href))
6765 continue;
6766 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006767 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006768 found = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006769 ctxt->cur = (xmlNodePtr) attributes;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006770
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006771 if (attributes->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006772 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
6773 "Internal error: attribute %s type not resolved\n",
6774 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006775 continue;
6776 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006777
6778 if (attributes->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
William M. Bracke7091952004-05-11 15:09:58 +00006779 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INVALIDATTR,
6780 "attribute %s on %s is prohibited\n",
6781 attributes->name, elem->name);
6782 /* Setting the state to XML_SCHEMAS_ATTR_CHECKED seems
6783 * not very logical but it suppresses the
6784 * "attribute is unknown" error report. Please change
6785 * this if you know better */
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006786 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6787 break;
6788 }
6789
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006790 value = xmlNodeListGetString(elem->doc, attr->children, 1);
6791 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6792 value);
6793 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006794 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
6795 XML_SCHEMAS_ERR_ATTRINVALID,
6796 "attribute %s on %s does not match type\n",
6797 attr->name, elem->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006798 } else {
6799 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6800 }
6801 if (value != NULL) {
6802 xmlFree(value);
6803 }
6804 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006805 if ((!found) && (attributes->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
William M. Bracke7091952004-05-11 15:09:58 +00006806 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_MISSING,
6807 "required attribute %s on %s is missing\n",
6808 attributes->name, elem->name);
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006809 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006810 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006811 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006812 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006813}
6814
6815/**
6816 * xmlSchemaValidateElement:
6817 * @ctxt: a schema validation context
6818 * @elem: an element
6819 *
6820 * Validate an element in a tree
6821 *
6822 * Returns 0 if the element is schemas valid, a positive error code
6823 * number otherwise and -1 in case of internal or API error.
6824 */
6825static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006826xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6827{
Daniel Veillard4255d502002-04-16 15:50:10 +00006828 xmlSchemaElementPtr elemDecl;
6829 int ret, attrBase;
6830
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006831 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006832 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6833 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006834 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006835 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6836 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006837 }
6838 /*
6839 * special case whe elementFormDefault is unqualified for top-level elem.
6840 */
William M. Bracke7091952004-05-11 15:09:58 +00006841 /*
6842 * This was removed, since elementFormDefault does not apply to top-level
6843 * element declarations.
6844 */
6845 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006846 if ((elemDecl == NULL) && (elem->ns != NULL) &&
6847 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6848 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6849 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6850 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6851 elem->name, NULL, NULL);
6852 }
William M. Bracke7091952004-05-11 15:09:58 +00006853 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006854
Daniel Veillard4255d502002-04-16 15:50:10 +00006855 /*
6856 * 3.3.4 : 1
6857 */
6858 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006859 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
6860 "Element %s not declared\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006861 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006862 }
6863 if (elemDecl->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006864 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
6865 "Element %s has no type\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006866 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006867 }
6868 /*
6869 * Verify the attributes
6870 */
6871 attrBase = ctxt->attrBase;
6872 ctxt->attrBase = ctxt->attrNr;
6873 xmlSchemaRegisterAttributes(ctxt, elem->properties);
6874 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6875 /*
6876 * Verify the element content recursively
6877 */
6878 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006879 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6880 (xmlRegExecCallbacks)
6881 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006882#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006883 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006884#endif
6885 }
6886 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006887 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006888 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006889#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006890 xmlGenericError(xmlGenericErrorContext,
6891 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006892#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006893 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006894 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
6895 "Element %s content check failed\n",
6896 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006897 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006898 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
6899 "Element %s content check failed\n",
6900 elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006901#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006902 } else {
6903 xmlGenericError(xmlGenericErrorContext,
6904 "Element %s content check succeeded\n",
6905 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006906
6907#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006908 }
6909 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006910 }
6911 /*
6912 * Verify that all attributes were Schemas-validated
6913 */
6914 xmlSchemaCheckAttributes(ctxt, elem);
6915 ctxt->attrNr = ctxt->attrBase;
6916 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006917
6918 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006919}
6920
6921/**
6922 * xmlSchemaValidateDocument:
6923 * @ctxt: a schema validation context
6924 * @doc: a parsed document tree
6925 *
6926 * Validate a document tree in memory.
6927 *
6928 * Returns 0 if the document is schemas valid, a positive error code
6929 * number otherwise and -1 in case of internal or API error.
6930 */
6931static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006932xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6933{
Daniel Veillard4255d502002-04-16 15:50:10 +00006934 xmlNodePtr root;
6935 xmlSchemaElementPtr elemDecl;
William M. Bracke7091952004-05-11 15:09:58 +00006936 xmlNodePtr node;
Daniel Veillard4255d502002-04-16 15:50:10 +00006937
6938 root = xmlDocGetRootElement(doc);
6939 if (root == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006940 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
6941 "document has no root\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006942 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006943 }
William M. Bracke7091952004-05-11 15:09:58 +00006944
Daniel Veillard4255d502002-04-16 15:50:10 +00006945 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006946 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6947 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006948 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006949 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6950 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006951 /*
6952 * special case whe elementFormDefault is unqualified for top-level elem.
6953 */
6954 if ((elemDecl == NULL) && (root->ns != NULL) &&
6955 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
6956 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6957 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6958 root->name, NULL, NULL);
6959 }
6960
Daniel Veillard4255d502002-04-16 15:50:10 +00006961 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006962 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
6963 "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006964 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006965 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
6966 "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006967 }
6968 /*
6969 * Okay, start the recursive validation
6970 */
6971 xmlSchemaValidateElement(ctxt, root);
6972
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006973 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006974}
6975
6976/************************************************************************
6977 * *
6978 * SAX Validation code *
6979 * *
6980 ************************************************************************/
6981
6982/************************************************************************
6983 * *
6984 * Validation interfaces *
6985 * *
6986 ************************************************************************/
6987
6988/**
6989 * xmlSchemaNewValidCtxt:
6990 * @schema: a precompiled XML Schemas
6991 *
6992 * Create an XML Schemas validation context based on the given schema
6993 *
6994 * Returns the validation context or NULL in case of error
6995 */
6996xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006997xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
6998{
Daniel Veillard4255d502002-04-16 15:50:10 +00006999 xmlSchemaValidCtxtPtr ret;
7000
7001 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
7002 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007003 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007004 return (NULL);
7005 }
7006 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
7007 ret->schema = schema;
7008 ret->attrNr = 0;
7009 ret->attrMax = 10;
7010 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007011 sizeof
7012 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00007013 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007014 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
7015 free(ret);
7016 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007017 }
7018 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
7019 return (ret);
7020}
7021
7022/**
7023 * xmlSchemaFreeValidCtxt:
7024 * @ctxt: the schema validation context
7025 *
7026 * Free the resources associated to the schema validation context
7027 */
7028void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007029xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
7030{
Daniel Veillard4255d502002-04-16 15:50:10 +00007031 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007032 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007033 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007034 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00007035 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007036 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00007037 xmlFree(ctxt);
7038}
7039
7040/**
7041 * xmlSchemaSetValidErrors:
7042 * @ctxt: a schema validation context
7043 * @err: the error function
7044 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00007045 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00007046 *
7047 * Set the error and warning callback informations
7048 */
7049void
7050xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007051 xmlSchemaValidityErrorFunc err,
7052 xmlSchemaValidityWarningFunc warn, void *ctx)
7053{
Daniel Veillard4255d502002-04-16 15:50:10 +00007054 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007055 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007056 ctxt->error = err;
7057 ctxt->warning = warn;
7058 ctxt->userData = ctx;
7059}
7060
7061/**
7062 * xmlSchemaValidateDoc:
7063 * @ctxt: a schema validation context
7064 * @doc: a parsed document tree
7065 *
7066 * Validate a document tree in memory.
7067 *
7068 * Returns 0 if the document is schemas valid, a positive error code
7069 * number otherwise and -1 in case of internal or API error.
7070 */
7071int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007072xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
7073{
Daniel Veillard4255d502002-04-16 15:50:10 +00007074 int ret;
7075
7076 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007077 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007078
7079 ctxt->doc = doc;
7080 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007081 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007082}
7083
7084/**
7085 * xmlSchemaValidateStream:
7086 * @ctxt: a schema validation context
7087 * @input: the input to use for reading the data
7088 * @enc: an optional encoding information
7089 * @sax: a SAX handler for the resulting events
7090 * @user_data: the context to provide to the SAX handler.
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 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007097int
Daniel Veillard4255d502002-04-16 15:50:10 +00007098xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007099 xmlParserInputBufferPtr input, xmlCharEncoding enc,
7100 xmlSAXHandlerPtr sax, void *user_data)
7101{
Daniel Veillard4255d502002-04-16 15:50:10 +00007102 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007103 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007104 ctxt->input = input;
7105 ctxt->enc = enc;
7106 ctxt->sax = sax;
7107 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007108 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007109}
7110
7111#endif /* LIBXML_SCHEMAS_ENABLED */