blob: 4aa9dc41cb8e0185140f649694e3bd4056cbdf4d [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010/*
11 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
15 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016#define IN_LIBXML
17#include "libxml.h"
18
19#ifdef LIBXML_SCHEMAS_ENABLED
20
21#include <string.h>
22#include <libxml/xmlmemory.h>
23#include <libxml/parser.h>
24#include <libxml/parserInternals.h>
25#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000026#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000027
28#include <libxml/xmlschemas.h>
29#include <libxml/schemasInternals.h>
30#include <libxml/xmlschemastypes.h>
31#include <libxml/xmlautomata.h>
32#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000033#include <libxml/dict.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000034
Daniel Veillarda84c0b32003-06-02 16:58:46 +000035/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000036
Daniel Veillard82bbbd42003-05-11 20:16:09 +000037/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000038
Daniel Veillard82bbbd42003-05-11 20:16:09 +000039/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000040
Daniel Veillard118aed72002-09-24 14:13:13 +000041/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000042
Daniel Veillard4255d502002-04-16 15:50:10 +000043/* #define DEBUG_AUTOMATA 1 */
44
45#define UNBOUNDED (1 << 30)
46#define TODO \
47 xmlGenericError(xmlGenericErrorContext, \
48 "Unimplemented block at %s:%d\n", \
49 __FILE__, __LINE__);
50
Daniel Veillard5a872412002-05-22 06:40:27 +000051#define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
52
Daniel Veillard4255d502002-04-16 15:50:10 +000053/*
54 * The XML Schemas namespaces
55 */
56static const xmlChar *xmlSchemaNs = (const xmlChar *)
57 "http://www.w3.org/2001/XMLSchema";
58
59static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
60 "http://www.w3.org/2001/XMLSchema-instance";
61
62#define IS_SCHEMA(node, type) \
63 ((node != NULL) && (node->ns != NULL) && \
64 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
65 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
66
67#define XML_SCHEMAS_PARSE_ERROR 1
68
Daniel Veillardbd2904b2003-11-25 15:38:59 +000069#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
70
Daniel Veillard4255d502002-04-16 15:50:10 +000071struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000072 void *userData; /* user specific data block */
73 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
74 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +000075 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000076 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +000077 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +000078
Daniel Veillardbe9c6322003-11-22 20:37:51 +000079 xmlSchemaPtr topschema; /* The main schema */
80 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
81
Daniel Veillardd0c9c322003-10-10 00:49:42 +000082 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000083 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +000084 int counter;
85
Daniel Veillardbe9c6322003-11-22 20:37:51 +000086 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000087 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000088 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +000089
Daniel Veillardd0c9c322003-10-10 00:49:42 +000090 const char *buffer;
91 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +000092
Daniel Veillard4255d502002-04-16 15:50:10 +000093 /*
94 * Used to build complex element content models
95 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000096 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +000097 xmlAutomataStatePtr start;
98 xmlAutomataStatePtr end;
99 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000100
101 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000102 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard4255d502002-04-16 15:50:10 +0000103};
104
105
106#define XML_SCHEMAS_ATTR_UNKNOWN 1
107#define XML_SCHEMAS_ATTR_CHECKED 2
108
109typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
110typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
111struct _xmlSchemaAttrState {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000112 xmlAttrPtr attr;
113 int state;
Daniel Veillard4255d502002-04-16 15:50:10 +0000114};
115
116/**
117 * xmlSchemaValidCtxt:
118 *
119 * A Schemas validation context
120 */
121
122struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000123 void *userData; /* user specific data block */
124 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
125 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000126 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000127
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000128 xmlSchemaPtr schema; /* The schema in use */
129 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000130 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000131 xmlCharEncoding enc;
132 xmlSAXHandlerPtr sax;
133 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000134
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000135 xmlDocPtr myDoc;
136 int err;
137 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000138
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000139 xmlNodePtr node;
140 xmlNodePtr cur;
141 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000142
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000143 xmlRegExecCtxtPtr regexp;
144 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000145
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000146 int attrNr;
147 int attrBase;
148 int attrMax;
149 xmlSchemaAttrStatePtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +0000150};
151
Daniel Veillard1d913862003-11-21 00:28:39 +0000152/*
153 * These are the entries in the schemas importSchemas hash table
154 */
155typedef struct _xmlSchemaImport xmlSchemaImport;
156typedef xmlSchemaImport *xmlSchemaImportPtr;
157struct _xmlSchemaImport {
158 const xmlChar *schemaLocation;
159 xmlSchemaPtr schema;
160};
Daniel Veillard4255d502002-04-16 15:50:10 +0000161
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000162/*
163 * These are the entries associated to includes in a schemas
164 */
165typedef struct _xmlSchemaInclude xmlSchemaInclude;
166typedef xmlSchemaInclude *xmlSchemaIncludePtr;
167struct _xmlSchemaInclude {
168 xmlSchemaIncludePtr next;
169
170 const xmlChar *schemaLocation;
171 xmlDocPtr doc;
172};
173
Daniel Veillard4255d502002-04-16 15:50:10 +0000174/************************************************************************
175 * *
176 * Some predeclarations *
177 * *
178 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000179static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
180 xmlSchemaTypePtr type,
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000181 const xmlChar * value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000182
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000183static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
184 xmlSchemaPtr schema,
185 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +0000186static int
187xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
188 xmlSchemaTypePtr type,
189 const xmlChar * value,
190 int fireErrors);
191
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000192/************************************************************************
193 * *
194 * Datatype error handlers *
195 * *
196 ************************************************************************/
197
198/**
199 * xmlSchemaPErrMemory:
200 * @node: a context node
201 * @extra: extra informations
202 *
203 * Handle an out of memory condition
204 */
205static void
206xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
207 const char *extra, xmlNodePtr node)
208{
209 if (ctxt != NULL)
210 ctxt->nberrors++;
211 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
212 extra);
213}
214
215/**
216 * xmlSchemaPErr:
217 * @ctxt: the parsing context
218 * @node: the context node
219 * @error: the error code
220 * @msg: the error message
221 * @str1: extra data
222 * @str2: extra data
223 *
224 * Handle a parser error
225 */
226static void
227xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
228 const char *msg, const xmlChar * str1, const xmlChar * str2)
229{
230 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000231 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000232 void *data = NULL;
233
234 if (ctxt != NULL) {
235 ctxt->nberrors++;
236 channel = ctxt->error;
237 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000238 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000239 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000240 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000241 error, XML_ERR_ERROR, NULL, 0,
242 (const char *) str1, (const char *) str2, NULL, 0, 0,
243 msg, str1, str2);
244}
245
246/**
247 * xmlSchemaPErr2:
248 * @ctxt: the parsing context
249 * @node: the context node
250 * @node: the current child
251 * @error: the error code
252 * @msg: the error message
253 * @str1: extra data
254 * @str2: extra data
255 *
256 * Handle a parser error
257 */
258static void
259xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
260 xmlNodePtr child, int error,
261 const char *msg, const xmlChar * str1, const xmlChar * str2)
262{
263 if (child != NULL)
264 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
265 else
266 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
267}
268
269/**
270 * xmlSchemaVTypeErrMemory:
271 * @node: a context node
272 * @extra: extra informations
273 *
274 * Handle an out of memory condition
275 */
276static void
277xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
278 const char *extra, xmlNodePtr node)
279{
280 if (ctxt != NULL) {
281 ctxt->nberrors++;
282 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
283 }
284 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
285 extra);
286}
287
288/**
289 * xmlSchemaVErr3:
290 * @ctxt: the validation context
291 * @node: the context node
292 * @error: the error code
293 * @msg: the error message
294 * @str1: extra data
295 * @str2: extra data
296 * @str3: extra data
297 *
298 * Handle a validation error
299 */
300static void
301xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
302 const char *msg, const xmlChar *str1, const xmlChar *str2,
303 const xmlChar *str3)
304{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000305 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000306 xmlGenericErrorFunc channel = NULL;
307 void *data = NULL;
308
309 if (ctxt != NULL) {
310 ctxt->nberrors++;
311 ctxt->err = error;
312 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000313 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000314 data = ctxt->userData;
315 }
316 /* reajust to global error numbers */
317 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000318 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000319 error, XML_ERR_ERROR, NULL, 0,
320 (const char *) str1, (const char *) str2,
321 (const char *) str3, 0, 0,
322 msg, str1, str2, str3);
323}
324/**
325 * xmlSchemaVErr:
326 * @ctxt: the validation context
327 * @node: the context node
328 * @error: the error code
329 * @msg: the error message
330 * @str1: extra data
331 * @str2: extra data
332 *
333 * Handle a validation error
334 */
335static void
336xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
337 const char *msg, const xmlChar * str1, const xmlChar * str2)
338{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000339 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000340 xmlGenericErrorFunc channel = NULL;
341 void *data = NULL;
342
343 if (ctxt != NULL) {
344 ctxt->nberrors++;
345 ctxt->err = error;
346 channel = ctxt->error;
347 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000348 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000349 }
350 /* reajust to global error numbers */
351 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000352 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000353 error, XML_ERR_ERROR, NULL, 0,
354 (const char *) str1, (const char *) str2, NULL, 0, 0,
355 msg, str1, str2);
356}
Daniel Veillard4255d502002-04-16 15:50:10 +0000357
358/************************************************************************
359 * *
360 * Allocation functions *
361 * *
362 ************************************************************************/
363
364/**
365 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +0000366 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000367 *
368 * Allocate a new Schema structure.
369 *
370 * Returns the newly allocated structure or NULL in case or error
371 */
372static xmlSchemaPtr
373xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
374{
375 xmlSchemaPtr ret;
376
377 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
378 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000379 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000380 return (NULL);
381 }
382 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000383 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000384 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000385
386 return (ret);
387}
388
389/**
390 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000391 *
392 * Allocate a new Facet structure.
393 *
394 * Returns the newly allocated structure or NULL in case or error
395 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000396xmlSchemaFacetPtr
397xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000398{
399 xmlSchemaFacetPtr ret;
400
401 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
402 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000403 return (NULL);
404 }
405 memset(ret, 0, sizeof(xmlSchemaFacet));
406
407 return (ret);
408}
409
410/**
411 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +0000412 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000413 * @node: a node
414 *
415 * Allocate a new annotation structure.
416 *
417 * Returns the newly allocated structure or NULL in case or error
418 */
419static xmlSchemaAnnotPtr
420xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
421{
422 xmlSchemaAnnotPtr ret;
423
424 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
425 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000426 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000427 return (NULL);
428 }
429 memset(ret, 0, sizeof(xmlSchemaAnnot));
430 ret->content = node;
431 return (ret);
432}
433
434/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000435 * xmlSchemaFreeAnnot:
436 * @annot: a schema type structure
437 *
438 * Deallocate a annotation structure
439 */
440static void
441xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
442{
443 if (annot == NULL)
444 return;
445 xmlFree(annot);
446}
447
448/**
Daniel Veillard1d913862003-11-21 00:28:39 +0000449 * xmlSchemaFreeImport:
450 * @import: a schema import structure
451 *
452 * Deallocate an import structure
453 */
454static void
455xmlSchemaFreeImport(xmlSchemaImportPtr import)
456{
457 if (import == NULL)
458 return;
459
460 xmlSchemaFree(import->schema);
Daniel Veillard1d913862003-11-21 00:28:39 +0000461 xmlFree(import);
462}
463
464/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000465 * xmlSchemaFreeInclude:
466 * @include: a schema include structure
467 *
468 * Deallocate an include structure
469 */
470static void
471xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
472{
473 if (include == NULL)
474 return;
475
476 xmlFreeDoc(include->doc);
477 xmlFree(include);
478}
479
480/**
481 * xmlSchemaFreeIncludeList:
482 * @includes: a schema include list
483 *
484 * Deallocate an include structure
485 */
486static void
487xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
488{
489 xmlSchemaIncludePtr next;
490
491 while (includes != NULL) {
492 next = includes->next;
493 xmlSchemaFreeInclude(includes);
494 includes = next;
495 }
496}
497
498/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000499 * xmlSchemaFreeNotation:
500 * @schema: a schema notation structure
501 *
502 * Deallocate a Schema Notation structure.
503 */
504static void
505xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
506{
507 if (nota == NULL)
508 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000509 xmlFree(nota);
510}
511
512/**
513 * xmlSchemaFreeAttribute:
514 * @schema: a schema attribute structure
515 *
516 * Deallocate a Schema Attribute structure.
517 */
518static void
519xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
520{
521 if (attr == NULL)
522 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000523 xmlFree(attr);
524}
525
526/**
527 * xmlSchemaFreeAttributeGroup:
528 * @schema: a schema attribute group structure
529 *
530 * Deallocate a Schema Attribute Group structure.
531 */
532static void
533xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
534{
535 if (attr == NULL)
536 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000537 xmlFree(attr);
538}
539
540/**
541 * xmlSchemaFreeElement:
542 * @schema: a schema element structure
543 *
544 * Deallocate a Schema Element structure.
545 */
546static void
547xmlSchemaFreeElement(xmlSchemaElementPtr elem)
548{
549 if (elem == NULL)
550 return;
Daniel Veillard32370232002-10-16 14:08:14 +0000551 if (elem->annot != NULL)
552 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000553 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000554 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000555 xmlFree(elem);
556}
557
558/**
559 * xmlSchemaFreeFacet:
560 * @facet: a schema facet structure
561 *
562 * Deallocate a Schema Facet structure.
563 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000564void
Daniel Veillard4255d502002-04-16 15:50:10 +0000565xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
566{
567 if (facet == NULL)
568 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000569 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000570 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000571 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000572 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000573 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000574 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000575 xmlFree(facet);
576}
577
578/**
579 * xmlSchemaFreeType:
580 * @type: a schema type structure
581 *
582 * Deallocate a Schema Type structure.
583 */
584void
585xmlSchemaFreeType(xmlSchemaTypePtr type)
586{
587 if (type == NULL)
588 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000589 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000590 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000591 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000592 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000593
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000594 facet = type->facets;
595 while (facet != NULL) {
596 next = facet->next;
597 xmlSchemaFreeFacet(facet);
598 facet = next;
599 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000600 }
601 xmlFree(type);
602}
603
604/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000605 * xmlSchemaFreeTypeList:
606 * @type: a schema type structure
607 *
608 * Deallocate a Schema Type structure.
609 */
610static void
611xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
612{
613 xmlSchemaTypePtr next;
614
615 while (type != NULL) {
616 next = type->redef;
617 xmlSchemaFreeType(type);
618 type = next;
619 }
620}
621
622/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000623 * xmlSchemaFree:
624 * @schema: a schema structure
625 *
626 * Deallocate a Schema structure.
627 */
628void
629xmlSchemaFree(xmlSchemaPtr schema)
630{
631 if (schema == NULL)
632 return;
633
Daniel Veillard4255d502002-04-16 15:50:10 +0000634 if (schema->notaDecl != NULL)
635 xmlHashFree(schema->notaDecl,
636 (xmlHashDeallocator) xmlSchemaFreeNotation);
637 if (schema->attrDecl != NULL)
638 xmlHashFree(schema->attrDecl,
639 (xmlHashDeallocator) xmlSchemaFreeAttribute);
640 if (schema->attrgrpDecl != NULL)
641 xmlHashFree(schema->attrgrpDecl,
642 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
643 if (schema->elemDecl != NULL)
644 xmlHashFree(schema->elemDecl,
645 (xmlHashDeallocator) xmlSchemaFreeElement);
646 if (schema->typeDecl != NULL)
647 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000648 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000649 if (schema->groupDecl != NULL)
650 xmlHashFree(schema->groupDecl,
651 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +0000652 if (schema->schemasImports != NULL)
653 xmlHashFree(schema->schemasImports,
654 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000655 if (schema->includes != NULL) {
656 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
657 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000658 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000659 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +0000660 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000661 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000662 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000663
664 xmlFree(schema);
665}
666
667/************************************************************************
668 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000669 * Debug functions *
670 * *
671 ************************************************************************/
672
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000673#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000674
Daniel Veillard4255d502002-04-16 15:50:10 +0000675/**
676 * xmlSchemaElementDump:
677 * @elem: an element
678 * @output: the file output
679 *
680 * Dump the element
681 */
682static void
683xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000684 const xmlChar * name ATTRIBUTE_UNUSED,
685 const xmlChar * context ATTRIBUTE_UNUSED,
686 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000687{
688 if (elem == NULL)
689 return;
690
691 fprintf(output, "Element ");
692 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000693 fprintf(output, "toplevel ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000694 fprintf(output, ": %s ", elem->name);
695 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000696 fprintf(output, "namespace '%s' ", namespace);
697
Daniel Veillard4255d502002-04-16 15:50:10 +0000698 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000699 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000700 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000701 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000702 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000703 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000704 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000705 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000706 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000707 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000708 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000709 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000710 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000711 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000712 fprintf(output, "\n");
713 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000714 fprintf(output, " ");
715 if (elem->minOccurs != 1)
716 fprintf(output, "min: %d ", elem->minOccurs);
717 if (elem->maxOccurs >= UNBOUNDED)
718 fprintf(output, "max: unbounded\n");
719 else if (elem->maxOccurs != 1)
720 fprintf(output, "max: %d\n", elem->maxOccurs);
721 else
722 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000723 }
724 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000725 fprintf(output, " type: %s", elem->namedType);
726 if (elem->namedTypeNs != NULL)
727 fprintf(output, " ns %s\n", elem->namedTypeNs);
728 else
729 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000730 }
731 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000732 fprintf(output, " substitutionGroup: %s", elem->substGroup);
733 if (elem->substGroupNs != NULL)
734 fprintf(output, " ns %s\n", elem->substGroupNs);
735 else
736 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000737 }
738 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000739 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000740}
741
742/**
743 * xmlSchemaAnnotDump:
744 * @output: the file output
745 * @annot: a annotation
746 *
747 * Dump the annotation
748 */
749static void
750xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
751{
752 xmlChar *content;
753
754 if (annot == NULL)
755 return;
756
757 content = xmlNodeGetContent(annot->content);
758 if (content != NULL) {
759 fprintf(output, " Annot: %s\n", content);
760 xmlFree(content);
761 } else
762 fprintf(output, " Annot: empty\n");
763}
764
765/**
766 * xmlSchemaTypeDump:
767 * @output: the file output
768 * @type: a type structure
769 *
770 * Dump a SchemaType structure
771 */
772static void
773xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
774{
775 if (type == NULL) {
776 fprintf(output, "Type: NULL\n");
777 return;
778 }
779 fprintf(output, "Type: ");
780 if (type->name != NULL)
781 fprintf(output, "%s, ", type->name);
782 else
783 fprintf(output, "no name");
784 switch (type->type) {
785 case XML_SCHEMA_TYPE_BASIC:
786 fprintf(output, "basic ");
787 break;
788 case XML_SCHEMA_TYPE_SIMPLE:
789 fprintf(output, "simple ");
790 break;
791 case XML_SCHEMA_TYPE_COMPLEX:
792 fprintf(output, "complex ");
793 break;
794 case XML_SCHEMA_TYPE_SEQUENCE:
795 fprintf(output, "sequence ");
796 break;
797 case XML_SCHEMA_TYPE_CHOICE:
798 fprintf(output, "choice ");
799 break;
800 case XML_SCHEMA_TYPE_ALL:
801 fprintf(output, "all ");
802 break;
803 case XML_SCHEMA_TYPE_UR:
804 fprintf(output, "ur ");
805 break;
806 case XML_SCHEMA_TYPE_RESTRICTION:
807 fprintf(output, "restriction ");
808 break;
809 case XML_SCHEMA_TYPE_EXTENSION:
810 fprintf(output, "extension ");
811 break;
812 default:
813 fprintf(output, "unknowntype%d ", type->type);
814 break;
815 }
816 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000817 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000818 }
819 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000820 case XML_SCHEMA_CONTENT_UNKNOWN:
821 fprintf(output, "unknown ");
822 break;
823 case XML_SCHEMA_CONTENT_EMPTY:
824 fprintf(output, "empty ");
825 break;
826 case XML_SCHEMA_CONTENT_ELEMENTS:
827 fprintf(output, "element ");
828 break;
829 case XML_SCHEMA_CONTENT_MIXED:
830 fprintf(output, "mixed ");
831 break;
832 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
833 fprintf(output, "mixed_or_elems ");
834 break;
835 case XML_SCHEMA_CONTENT_BASIC:
836 fprintf(output, "basic ");
837 break;
838 case XML_SCHEMA_CONTENT_SIMPLE:
839 fprintf(output, "simple ");
840 break;
841 case XML_SCHEMA_CONTENT_ANY:
842 fprintf(output, "any ");
843 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000844 }
845 fprintf(output, "\n");
846 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000847 fprintf(output, " ");
848 if (type->minOccurs != 1)
849 fprintf(output, "min: %d ", type->minOccurs);
850 if (type->maxOccurs >= UNBOUNDED)
851 fprintf(output, "max: unbounded\n");
852 else if (type->maxOccurs != 1)
853 fprintf(output, "max: %d\n", type->maxOccurs);
854 else
855 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000856 }
857 if (type->annot != NULL)
858 xmlSchemaAnnotDump(output, type->annot);
859 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000860 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000861
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000862 fprintf(output, " subtypes: ");
863 while (sub != NULL) {
864 fprintf(output, "%s ", sub->name);
865 sub = sub->next;
866 }
867 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000868 }
869
870}
871
872/**
873 * xmlSchemaDump:
874 * @output: the file output
875 * @schema: a schema structure
876 *
877 * Dump a Schema structure.
878 */
879void
880xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
881{
882 if (schema == NULL) {
883 fprintf(output, "Schemas: NULL\n");
884 return;
885 }
886 fprintf(output, "Schemas: ");
887 if (schema->name != NULL)
888 fprintf(output, "%s, ", schema->name);
889 else
890 fprintf(output, "no name, ");
891 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +0000892 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000893 else
894 fprintf(output, "no target namespace");
895 fprintf(output, "\n");
896 if (schema->annot != NULL)
897 xmlSchemaAnnotDump(output, schema->annot);
898
899 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
900 output);
901 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000902 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +0000903}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000904#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +0000905
906/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000907 * *
908 * Utilities *
909 * *
910 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000911
912/**
913 * xmlSchemaGetProp:
914 * @ctxt: the parser context
915 * @node: the node
916 * @name: the property name
917 *
918 * Read a attribute value and internalize the string
919 *
920 * Returns the string or NULL if not present.
921 */
922static const xmlChar *
923xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
924 const char *name)
925{
926 xmlChar *val;
927 const xmlChar *ret;
928
929 val = xmlGetProp(node, BAD_CAST name);
930 if (val == NULL)
931 return(NULL);
932 ret = xmlDictLookup(ctxt->dict, val, -1);
933 xmlFree(val);
934 return(ret);
935}
936
William M. Brack29aa7722004-05-12 00:27:56 +0000937#if 0
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000938/**
939 * xmlSchemaGetNamespace:
940 * @ctxt: the parser context
941 * @schema: the schemas containing the declaration
942 * @node: the node
943 * @qname: the QName to analyze
944 *
945 * Find the namespace name for the given declaration.
946 *
947 * Returns the local name for that declaration, as well as the namespace name
William M. Bracke7091952004-05-11 15:09:58 +0000948 * NOTE: This function is no longer used (Buchcik, May '04)
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000949 */
950static const xmlChar *
951xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
952 xmlNodePtr node, const xmlChar *qname,
953 const xmlChar **namespace) {
954 int len;
955 const xmlChar *name, *prefix, *def = NULL;
956 xmlNsPtr ns;
957
958 *namespace = NULL;
959
William M. Bracke7091952004-05-11 15:09:58 +0000960 /* TODO: The following seems to be not correct here:
961 * 1. The name of a declaration is a NCName, not a QName.
962 * 2. The attribute "targetNamespace" is allowed for the
963 * <schema> Element Information Item only.
964 * 3. One cannot evaluate the target namespace, by the type
965 * of declaration, since it is dependant on the xxxFormDefault
966 * of <schema> and the form attribute of an <element> or <attribute>.
967 */
968
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000969 if (xmlStrEqual(node->name, BAD_CAST "element") ||
970 xmlStrEqual(node->name, BAD_CAST "attribute") ||
971 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
972 xmlStrEqual(node->name, BAD_CAST "complexType")) {
973 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
974 }
975
William M. Bracke7091952004-05-11 15:09:58 +0000976
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000977 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
978 name = xmlSplitQName3(qname, &len);
979 if (name == NULL) {
980 if (def == NULL) {
981 if (xmlStrEqual(node->name, BAD_CAST "element")) {
982 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
983 *namespace = schema->targetNamespace;
984 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
985 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
986 *namespace = schema->targetNamespace;
987 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
988 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
989 *namespace = schema->targetNamespace;
990 }
991 } else {
992 *namespace = def;
993 }
994 return(qname);
995 }
William M. Bracke7091952004-05-11 15:09:58 +0000996
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000997 name = xmlDictLookup(ctxt->dict, name, -1);
998 prefix = xmlDictLookup(ctxt->dict, qname, len);
999 if (def != NULL) {
1000 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
1001 "%s: presence of both prefix %s and targetNamespace\n",
1002 node->name, prefix);
1003 }
1004 ns = xmlSearchNs(node->doc, node, prefix);
1005 if (ns == NULL) {
1006 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1007 "%s: the QName prefix %s is undefined\n",
1008 node->name, prefix);
1009 return(name);
1010 }
1011 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1012 return(name);
1013}
William M. Brack29aa7722004-05-12 00:27:56 +00001014#endif
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001015
1016/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00001017 * *
1018 * Parsing functions *
1019 * *
1020 ************************************************************************/
1021
1022/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001023 * xmlSchemaGetElem:
1024 * @schema: the schemas context
1025 * @name: the element name
1026 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001027 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001028 *
1029 * Lookup a an element in the schemas or the accessible schemas
1030 *
1031 * Returns the element definition or NULL if not found.
1032 */
1033static xmlSchemaElementPtr
1034xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001035 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001036{
1037 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001038 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001039
1040 if ((name == NULL) || (schema == NULL))
1041 return (NULL);
1042
1043 if (namespace == NULL) {
1044 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001045 if ((ret != NULL) &&
1046 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001047 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001048 }
William M. Bracke7091952004-05-11 15:09:58 +00001049 /*
1050 * This one was removed, since top level element declarations have
1051 * the target namespace specified in targetNamespace of the <schema>
1052 * information element, even if elementFormDefault is "unqualified".
1053 */
1054
1055 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001056 if (xmlStrEqual(namespace, schema->targetNamespace))
1057 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1058 else
1059 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001060 if ((ret != NULL) &&
1061 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001062 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001063 }
William M. Bracke7091952004-05-11 15:09:58 +00001064 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001065 } else {
1066 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001067 if ((ret != NULL) &&
1068 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001069 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001070 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001071 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00001072 if (level > 0)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001073 import = xmlHashLookup(schema->schemasImports, namespace);
1074 if (import != NULL)
Daniel Veillardf2a12832003-11-24 13:04:35 +00001075 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001076#ifdef DEBUG
1077 if (ret == NULL) {
1078 if (namespace == NULL)
1079 fprintf(stderr, "Unable to lookup type %s", name);
1080 else
1081 fprintf(stderr, "Unable to lookup type %s:%s", name,
1082 namespace);
1083 }
1084#endif
1085 return (ret);
1086}
1087
1088/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001089 * xmlSchemaGetType:
1090 * @schema: the schemas context
1091 * @name: the type name
1092 * @ns: the type namespace
1093 *
1094 * Lookup a type in the schemas or the predefined types
1095 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001096 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001097 */
1098static xmlSchemaTypePtr
1099xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001100 const xmlChar * namespace)
1101{
Daniel Veillard4255d502002-04-16 15:50:10 +00001102 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001103 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001104
1105 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001106 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001107 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001108 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
1109 if (ret != NULL)
1110 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001111 }
1112 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001113 if (ret != NULL)
1114 return (ret);
1115 import = xmlHashLookup(schema->schemasImports, namespace);
1116 if (import != NULL)
1117 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001118#ifdef DEBUG
1119 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001120 if (namespace == NULL)
1121 fprintf(stderr, "Unable to lookup type %s", name);
1122 else
1123 fprintf(stderr, "Unable to lookup type %s:%s", name,
1124 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001125 }
1126#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001127 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001128}
1129
1130/************************************************************************
1131 * *
1132 * Parsing functions *
1133 * *
1134 ************************************************************************/
1135
1136#define IS_BLANK_NODE(n) \
1137 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1138
1139/**
1140 * xmlSchemaIsBlank:
1141 * @str: a string
1142 *
1143 * Check if a string is ignorable
1144 *
1145 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1146 */
1147static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001148xmlSchemaIsBlank(xmlChar * str)
1149{
Daniel Veillard4255d502002-04-16 15:50:10 +00001150 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001151 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001152 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001153 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001154 return (0);
1155 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001156 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001157 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001158}
1159
1160/**
1161 * xmlSchemaAddNotation:
1162 * @ctxt: a schema validation context
1163 * @schema: the schema being built
1164 * @name: the item name
1165 *
1166 * Add an XML schema Attrribute declaration
1167 * *WARNING* this interface is highly subject to change
1168 *
1169 * Returns the new struture or NULL in case of error
1170 */
1171static xmlSchemaNotationPtr
1172xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001173 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001174{
1175 xmlSchemaNotationPtr ret = NULL;
1176 int val;
1177
1178 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1179 return (NULL);
1180
1181 if (schema->notaDecl == NULL)
1182 schema->notaDecl = xmlHashCreate(10);
1183 if (schema->notaDecl == NULL)
1184 return (NULL);
1185
1186 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1187 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001188 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001189 return (NULL);
1190 }
1191 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001192 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001193 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1194 ret);
1195 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001196 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1197 XML_SCHEMAP_REDEFINED_NOTATION,
1198 "Notation %s already defined\n",
1199 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001200 xmlFree(ret);
1201 return (NULL);
1202 }
1203 return (ret);
1204}
1205
1206
1207/**
1208 * xmlSchemaAddAttribute:
1209 * @ctxt: a schema validation context
1210 * @schema: the schema being built
1211 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001212 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001213 *
1214 * Add an XML schema Attrribute declaration
1215 * *WARNING* this interface is highly subject to change
1216 *
1217 * Returns the new struture or NULL in case of error
1218 */
1219static xmlSchemaAttributePtr
1220xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001221 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001222{
1223 xmlSchemaAttributePtr ret = NULL;
1224 int val;
1225
1226 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1227 return (NULL);
1228
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001229#ifdef DEBUG
1230 fprintf(stderr, "Adding attribute %s\n", name);
1231 if (namespace != NULL)
1232 fprintf(stderr, " target namespace %s\n", namespace);
1233#endif
1234
Daniel Veillard4255d502002-04-16 15:50:10 +00001235 if (schema->attrDecl == NULL)
1236 schema->attrDecl = xmlHashCreate(10);
1237 if (schema->attrDecl == NULL)
1238 return (NULL);
1239
1240 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1241 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001242 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001243 return (NULL);
1244 }
1245 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001246 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1247 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001248 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001249 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001250 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001251 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1252 XML_SCHEMAP_REDEFINED_ATTR,
1253 "Attribute %s already defined\n",
1254 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001255 xmlFree(ret);
1256 return (NULL);
1257 }
1258 return (ret);
1259}
1260
1261/**
1262 * xmlSchemaAddAttributeGroup:
1263 * @ctxt: a schema validation context
1264 * @schema: the schema being built
1265 * @name: the item name
1266 *
1267 * Add an XML schema Attrribute Group declaration
1268 *
1269 * Returns the new struture or NULL in case of error
1270 */
1271static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001272xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1273 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001274{
1275 xmlSchemaAttributeGroupPtr ret = NULL;
1276 int val;
1277
1278 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1279 return (NULL);
1280
1281 if (schema->attrgrpDecl == NULL)
1282 schema->attrgrpDecl = xmlHashCreate(10);
1283 if (schema->attrgrpDecl == NULL)
1284 return (NULL);
1285
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001286 ret =
1287 (xmlSchemaAttributeGroupPtr)
1288 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001289 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001290 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001291 return (NULL);
1292 }
1293 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001294 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001295 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001296 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001297 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001298 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1299 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1300 "Attribute group %s already defined\n",
1301 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001302 xmlFree(ret);
1303 return (NULL);
1304 }
1305 return (ret);
1306}
1307
1308/**
1309 * xmlSchemaAddElement:
1310 * @ctxt: a schema validation context
1311 * @schema: the schema being built
1312 * @name: the type name
1313 * @namespace: the type namespace
1314 *
1315 * Add an XML schema Element declaration
1316 * *WARNING* this interface is highly subject to change
1317 *
1318 * Returns the new struture or NULL in case of error
1319 */
1320static xmlSchemaElementPtr
1321xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1322 const xmlChar * name, const xmlChar * namespace)
1323{
1324 xmlSchemaElementPtr ret = NULL;
1325 int val;
1326
1327 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1328 return (NULL);
1329
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001330#ifdef DEBUG
1331 fprintf(stderr, "Adding element %s\n", name);
1332 if (namespace != NULL)
1333 fprintf(stderr, " target namespace %s\n", namespace);
1334#endif
1335
Daniel Veillard4255d502002-04-16 15:50:10 +00001336 if (schema->elemDecl == NULL)
1337 schema->elemDecl = xmlHashCreate(10);
1338 if (schema->elemDecl == NULL)
1339 return (NULL);
1340
1341 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1342 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001343 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001344 return (NULL);
1345 }
1346 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001347 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1348 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001349 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001350 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001351 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001352 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001353
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001354 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001355 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1356 namespace, ret);
1357 if (val != 0) {
1358 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1359 XML_SCHEMAP_REDEFINED_ELEMENT,
1360 "Element %s already defined\n",
1361 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001362 xmlFree(ret);
1363 return (NULL);
1364 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001365 }
1366 return (ret);
1367}
1368
1369/**
1370 * xmlSchemaAddType:
1371 * @ctxt: a schema validation context
1372 * @schema: the schema being built
1373 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001374 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001375 *
1376 * Add an XML schema Simple Type definition
1377 * *WARNING* this interface is highly subject to change
1378 *
1379 * Returns the new struture or NULL in case of error
1380 */
1381static xmlSchemaTypePtr
1382xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001383 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001384{
1385 xmlSchemaTypePtr ret = NULL;
1386 int val;
1387
1388 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1389 return (NULL);
1390
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001391#ifdef DEBUG
1392 fprintf(stderr, "Adding type %s\n", name);
1393 if (namespace != NULL)
1394 fprintf(stderr, " target namespace %s\n", namespace);
1395#endif
1396
Daniel Veillard4255d502002-04-16 15:50:10 +00001397 if (schema->typeDecl == NULL)
1398 schema->typeDecl = xmlHashCreate(10);
1399 if (schema->typeDecl == NULL)
1400 return (NULL);
1401
1402 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1403 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001404 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001405 return (NULL);
1406 }
1407 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001408 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001409 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001410 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001411 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001412 if (ctxt->includes == 0) {
1413 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1414 XML_SCHEMAP_REDEFINED_TYPE,
1415 "Type %s already defined\n",
1416 name, NULL);
1417 xmlFree(ret);
1418 return (NULL);
1419 } else {
1420 xmlSchemaTypePtr prev;
1421
1422 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1423 if (prev == NULL) {
1424 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1425 XML_ERR_INTERNAL_ERROR,
1426 "Internal error on type %s definition\n",
1427 name, NULL);
1428 xmlFree(ret);
1429 return (NULL);
1430 }
1431 ret->redef = prev->redef;
1432 prev->redef = ret;
1433 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001434 }
1435 ret->minOccurs = 1;
1436 ret->maxOccurs = 1;
1437
1438 return (ret);
1439}
1440
1441/**
1442 * xmlSchemaAddGroup:
1443 * @ctxt: a schema validation context
1444 * @schema: the schema being built
1445 * @name: the group name
1446 *
1447 * Add an XML schema Group definition
1448 *
1449 * Returns the new struture or NULL in case of error
1450 */
1451static xmlSchemaTypePtr
1452xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001453 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001454{
1455 xmlSchemaTypePtr ret = NULL;
1456 int val;
1457
1458 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1459 return (NULL);
1460
1461 if (schema->groupDecl == NULL)
1462 schema->groupDecl = xmlHashCreate(10);
1463 if (schema->groupDecl == NULL)
1464 return (NULL);
1465
1466 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1467 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001468 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001469 return (NULL);
1470 }
1471 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001472 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001473 val =
1474 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1475 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001476 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001477 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1478 XML_SCHEMAP_REDEFINED_GROUP,
1479 "Group %s already defined\n",
1480 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001481 xmlFree(ret);
1482 return (NULL);
1483 }
1484 ret->minOccurs = 1;
1485 ret->maxOccurs = 1;
1486
1487 return (ret);
1488}
1489
1490/************************************************************************
1491 * *
1492 * Utilities for parsing *
1493 * *
1494 ************************************************************************/
1495
1496/**
1497 * xmlGetQNameProp:
1498 * @ctxt: a schema validation context
1499 * @node: a subtree containing XML Schema informations
1500 * @name: the attribute name
1501 * @namespace: the result namespace if any
1502 *
1503 * Extract a QName Attribute value
1504 *
1505 * Returns the NCName or NULL if not found, and also update @namespace
1506 * with the namespace URI
1507 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001508static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001509xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001510 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001511{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001512 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001513 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001514 const xmlChar *ret, *prefix;
1515 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001516
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001517 *namespace = NULL;
1518 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001519 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001520 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001521
Daniel Veillardba0153a2004-04-01 10:42:31 +00001522 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00001523 ns = xmlSearchNs(node->doc, node, 0);
1524 if (ns) {
1525 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1526 return (val);
1527 }
1528 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001529 ret = xmlSplitQName3(val, &len);
1530 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001531 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001532 }
1533 ret = xmlDictLookup(ctxt->dict, ret, -1);
1534 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001535
1536 ns = xmlSearchNs(node->doc, node, prefix);
1537 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001538 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1539 "Attribute %s: the QName prefix %s is undefined\n",
1540 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001541 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001542 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001543 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001544 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001545}
1546
1547/**
1548 * xmlGetMaxOccurs:
1549 * @ctxt: a schema validation context
1550 * @node: a subtree containing XML Schema informations
1551 *
1552 * Get the maxOccurs property
1553 *
1554 * Returns the default if not found, or the value
1555 */
1556static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001557xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1558{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001559 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001560 int ret = 0;
1561
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001562 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001563 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001564 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001565
1566 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001567 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001568 }
1569
1570 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001571 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001572 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001573 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001574 ret = ret * 10 + (*cur - '0');
1575 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001576 }
William M. Brack76e95df2003-10-18 16:20:14 +00001577 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001578 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001579 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001580 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1581 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001582 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001583 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001584 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001585}
1586
1587/**
1588 * xmlGetMinOccurs:
1589 * @ctxt: a schema validation context
1590 * @node: a subtree containing XML Schema informations
1591 *
1592 * Get the minOccurs property
1593 *
1594 * Returns the default if not found, or the value
1595 */
1596static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001597xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1598{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001599 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001600 int ret = 0;
1601
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001602 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001603 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001604 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001605
1606 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001607 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001608 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001609 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001610 ret = ret * 10 + (*cur - '0');
1611 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001612 }
William M. Brack76e95df2003-10-18 16:20:14 +00001613 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001614 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001615 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001616 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1617 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001618 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001619 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001620 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001621}
1622
1623/**
1624 * xmlGetBooleanProp:
1625 * @ctxt: a schema validation context
1626 * @node: a subtree containing XML Schema informations
1627 * @name: the attribute name
1628 * @def: the default value
1629 *
1630 * Get is a bolean property is set
1631 *
1632 * Returns the default if not found, 0 if found to be false,
1633 * 1 if found to be true
1634 */
1635static int
1636xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001637 const char *name, int def)
1638{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001639 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001640
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001641 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001642 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001643 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001644
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001645 if (xmlStrEqual(val, BAD_CAST "true"))
1646 def = 1;
1647 else if (xmlStrEqual(val, BAD_CAST "false"))
1648 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001649 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001650 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1651 "Attribute %s: the value %s is not boolean\n",
1652 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001653 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001654 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001655}
1656
1657/************************************************************************
1658 * *
1659 * Shema extraction from an Infoset *
1660 * *
1661 ************************************************************************/
1662static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1663 ctxt, xmlSchemaPtr schema,
1664 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001665static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1666 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001667 xmlSchemaPtr schema,
1668 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001669static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1670 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001671 xmlSchemaPtr schema,
1672 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001673 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001674static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1675 xmlSchemaPtr schema,
1676 xmlNodePtr node);
1677static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1678 xmlSchemaPtr schema,
1679 xmlNodePtr node);
1680static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1681 ctxt,
1682 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00001683 xmlNodePtr node,
1684 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00001685static xmlSchemaAttributeGroupPtr
1686xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1687 xmlSchemaPtr schema, xmlNodePtr node);
1688static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1689 xmlSchemaPtr schema,
1690 xmlNodePtr node);
1691static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1692 xmlSchemaPtr schema,
1693 xmlNodePtr node);
1694static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001695xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1696 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001697
1698/**
1699 * xmlSchemaParseAttrDecls:
1700 * @ctxt: a schema validation context
1701 * @schema: the schema being built
1702 * @node: a subtree containing XML Schema informations
1703 * @type: the hosting type
1704 *
1705 * parse a XML schema attrDecls declaration corresponding to
1706 * <!ENTITY % attrDecls
1707 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1708 */
1709static xmlNodePtr
1710xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1711 xmlNodePtr child, xmlSchemaTypePtr type)
1712{
1713 xmlSchemaAttributePtr lastattr, attr;
1714
1715 lastattr = NULL;
1716 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001717 (IS_SCHEMA(child, "attributeGroup"))) {
1718 attr = NULL;
1719 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00001720 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001721 } else if (IS_SCHEMA(child, "attributeGroup")) {
1722 attr = (xmlSchemaAttributePtr)
1723 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1724 }
1725 if (attr != NULL) {
1726 if (lastattr == NULL) {
1727 type->attributes = attr;
1728 lastattr = attr;
1729 } else {
1730 lastattr->next = attr;
1731 lastattr = attr;
1732 }
1733 }
1734 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001735 }
1736 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001737 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1738 if (attr != NULL) {
1739 if (lastattr == NULL) {
1740 type->attributes = attr;
1741 lastattr = attr;
1742 } else {
1743 lastattr->next = attr;
1744 lastattr = attr;
1745 }
1746 }
1747 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001748 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001749 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001750}
1751
1752/**
1753 * xmlSchemaParseAnnotation:
1754 * @ctxt: a schema validation context
1755 * @schema: the schema being built
1756 * @node: a subtree containing XML Schema informations
1757 *
1758 * parse a XML schema Attrribute declaration
1759 * *WARNING* this interface is highly subject to change
1760 *
William M. Bracke7091952004-05-11 15:09:58 +00001761 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00001762 * 1 in case of success.
1763 */
1764static xmlSchemaAnnotPtr
1765xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1766 xmlNodePtr node)
1767{
1768 xmlSchemaAnnotPtr ret;
1769
1770 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1771 return (NULL);
1772 ret = xmlSchemaNewAnnot(ctxt, node);
1773
1774 return (ret);
1775}
1776
1777/**
1778 * xmlSchemaParseFacet:
1779 * @ctxt: a schema validation context
1780 * @schema: the schema being built
1781 * @node: a subtree containing XML Schema informations
1782 *
1783 * parse a XML schema Facet declaration
1784 * *WARNING* this interface is highly subject to change
1785 *
1786 * Returns the new type structure or NULL in case of error
1787 */
1788static xmlSchemaFacetPtr
1789xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001790 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001791{
1792 xmlSchemaFacetPtr facet;
1793 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001794 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00001795
1796 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1797 return (NULL);
1798
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001799 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001800 if (facet == NULL) {
1801 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1802 return (NULL);
1803 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001804 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001805 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00001806 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001807 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1808 "Facet %s has no value\n", node->name, NULL);
1809 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001810 return (NULL);
1811 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001812 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001813 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001814 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001815 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001816 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001817 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001818 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001819 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001820 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001821 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001822 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001823 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001824 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001825 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001826 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001827 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001828 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001829 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001830 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001831 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001832 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001833 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1834 } else if (IS_SCHEMA(node, "minLength")) {
1835 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1836 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001837 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1838 "Unknown facet type %s\n", node->name, NULL);
1839 xmlSchemaFreeFacet(facet);
1840 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001841 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001842 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00001843 facet->value = value;
1844 child = node->children;
1845
1846 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001847 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1848 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001849 }
1850 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001851 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1852 "Facet %s has unexpected child content\n",
1853 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001854 }
1855 return (facet);
1856}
1857
1858/**
1859 * xmlSchemaParseAny:
1860 * @ctxt: a schema validation context
1861 * @schema: the schema being built
1862 * @node: a subtree containing XML Schema informations
1863 *
1864 * parse a XML schema Any declaration
1865 * *WARNING* this interface is highly subject to change
1866 *
1867 * Returns the new type structure or NULL in case of error
1868 */
1869static xmlSchemaTypePtr
1870xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1871 xmlNodePtr node)
1872{
1873 xmlSchemaTypePtr type;
1874 xmlNodePtr child = NULL;
1875 xmlChar name[30];
1876
1877 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1878 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001879 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001880 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001881 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001882 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001883 type->node = node;
1884 type->type = XML_SCHEMA_TYPE_ANY;
1885 child = node->children;
1886 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1887 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1888
1889 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001890 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1891 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001892 }
1893 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001894 xmlSchemaPErr2(ctxt, node, child,
1895 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1896 "Sequence %s has unexpected content\n", type->name,
1897 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001898 }
1899
1900 return (type);
1901}
1902
1903/**
1904 * xmlSchemaParseNotation:
1905 * @ctxt: a schema validation context
1906 * @schema: the schema being built
1907 * @node: a subtree containing XML Schema informations
1908 *
1909 * parse a XML schema Notation declaration
1910 *
1911 * Returns the new structure or NULL in case of error
1912 */
1913static xmlSchemaNotationPtr
1914xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001915 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001916{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001917 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00001918 xmlSchemaNotationPtr ret;
1919 xmlNodePtr child = NULL;
1920
1921 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1922 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001923 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001924 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001925 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1926 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001927 return (NULL);
1928 }
1929 ret = xmlSchemaAddNotation(ctxt, schema, name);
1930 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001931 return (NULL);
1932 }
1933 child = node->children;
1934 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001935 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1936 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001937 }
1938 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001939 xmlSchemaPErr2(ctxt, node, child,
1940 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1941 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001942 }
1943
1944 return (ret);
1945}
1946
1947/**
1948 * xmlSchemaParseAnyAttribute:
1949 * @ctxt: a schema validation context
1950 * @schema: the schema being built
1951 * @node: a subtree containing XML Schema informations
1952 *
1953 * parse a XML schema AnyAttrribute declaration
1954 * *WARNING* this interface is highly subject to change
1955 *
1956 * Returns an attribute def structure or NULL
1957 */
1958static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001959xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1960 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001961{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001962 const xmlChar *processContents;
Daniel Veillard4255d502002-04-16 15:50:10 +00001963 xmlSchemaAttributePtr ret;
1964 xmlNodePtr child = NULL;
1965 char name[100];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001966
Daniel Veillard4255d502002-04-16 15:50:10 +00001967
1968 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1969 return (NULL);
1970
1971 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
William M. Bracke7091952004-05-11 15:09:58 +00001972
1973 /* local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns); */
1974
1975 /*
1976 * TODO: namespace = ((##any | ##other) | List of (anyURI |
1977 * (##targetNamespace | * ##local)) ) : ##any
1978 */
1979 ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001980 if (ret == NULL) {
1981 return (NULL);
1982 }
William M. Bracke7091952004-05-11 15:09:58 +00001983 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001984 ret->id = xmlSchemaGetProp(ctxt, node, "id");
1985 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001986 if ((processContents == NULL)
1987 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1988 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1989 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1990 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1991 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1992 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001993 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001994 xmlSchemaPErr2(ctxt, node, child,
1995 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
William M. Bracke7091952004-05-11 15:09:58 +00001996 "anyAttribute has unexpected content "
1997 "for processContents: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001998 processContents, NULL);
1999 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00002000 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002001
2002 child = node->children;
2003 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002004 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2005 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002006 }
2007 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002008 xmlSchemaPErr2(ctxt, node, child,
2009 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
2010 "anyAttribute %s has unexpected content\n",
2011 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002012 }
2013
2014 return (ret);
2015}
2016
2017
2018/**
2019 * xmlSchemaParseAttribute:
2020 * @ctxt: a schema validation context
2021 * @schema: the schema being built
2022 * @node: a subtree containing XML Schema informations
2023 *
2024 * parse a XML schema Attrribute declaration
2025 * *WARNING* this interface is highly subject to change
2026 *
William M. Bracke7091952004-05-11 15:09:58 +00002027 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002028 */
2029static xmlSchemaAttributePtr
2030xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002031 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002032{
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002033 const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal;
Daniel Veillard4255d502002-04-16 15:50:10 +00002034 xmlSchemaAttributePtr ret;
2035 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002036 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002037 int hasRefType = 0;
William M. Bracke7091952004-05-11 15:09:58 +00002038
2039 /*
2040 * Note that the w3c spec assumes the schema to be validated with schema
2041 * for schemas beforehand.
2042 *
2043 * 3.2.3 Constraints on XML Representations of Attribute Declarations
2044 *
2045 * TODO: Complete implementation of:
2046 * 3.2.6 Schema Component Constraint: Attribute Declaration Properties
2047 * Correct
2048 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002049
2050 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2051 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002052
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002053 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002054 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002055 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002056 /* 3.2.3 : 3.1
2057 * One of ref or name must be present, but not both
2058 */
2059 if (ref == NULL) {
2060 xmlSchemaPErr(ctxt, node,
2061 XML_SCHEMAP_ATTR_NONAME_NOREF,
2062 "Attribute declaration has no \"name\" or \"ref\"\n",
2063 NULL, NULL);
2064 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002065 }
William M. Bracke7091952004-05-11 15:09:58 +00002066 hasRefType = 1;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002067 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2068 name = (const xmlChar *) buf;
2069 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002070 if (!topLevel) {
2071 /* 3.2.3 : 3.2
2072 * If ref is present, then all of <simpleType>,
2073 * form and type must be absent.
2074 */
2075 if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2076 xmlSchemaPErr(ctxt, node,
2077 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2078 "Attribute declaration %s has \"ref\", thus "
2079 "\"form\" must be absent\n", name, NULL);
2080 }
2081 if (xmlSchemaGetProp(ctxt, node, "type") != NULL) {
2082 xmlSchemaPErr(ctxt, node,
2083 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2084 "Attribute declaration %s has \"ref\", thus "
2085 "\"type\" must be absent\n", name, NULL);
2086 }
2087 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002088 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002089 const xmlChar *ns = NULL;
2090 /* 3.2.3 : 3.1
2091 * One of ref or name must be present, but not both
2092 */
2093 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2094 xmlSchemaPErr(ctxt, node,
2095 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2096 "Attribute declaration has both, \"name\" and "
2097 "\"ref\"\n", NULL, NULL);
2098 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002099
William M. Bracke7091952004-05-11 15:09:58 +00002100 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2101 /* Evaluate the target namespace */
2102 if (schema->targetNamespace != NULL) {
2103 if (topLevel) {
2104 ns = schema->targetNamespace;
2105 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2106 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2107 BAD_CAST "qualified")) {
2108 ns = schema->targetNamespace;
2109 }
2110 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2111 ns = schema->targetNamespace;
2112 }
2113 }
2114 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns);
2115
2116 /* 3.2.6 Schema Component Constraint: xmlns Not Allowed */
2117 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2118 xmlSchemaPErr(ctxt, node,
2119 XML_SCHEMAP_INVALID_ATTR_NAME,
2120 "The name of an attribute declaration must not match "
2121 "\"xmlns\".\n", NULL, NULL);
2122 }
2123
2124 /* 3.2.6 Schema Component Constraint: xsi: Not Allowed */
2125 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
2126 xmlSchemaPErr(ctxt, node,
2127 XML_SCHEMAP_INVALID_ATTR_NAME,
2128 "The target namespace of an attribute declaration, "
2129 "must not match \"http://www.w3.org/2001/"
2130 "XMLSchema-instance\"", NULL, NULL);
2131 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002132 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002133 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002134 return (NULL);
2135 }
William M. Bracke7091952004-05-11 15:09:58 +00002136 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
2137
2138 /* Handle the "use" attribute. */
2139 attrVal = xmlSchemaGetProp(ctxt, node, "use");
2140 if (attrVal != NULL) {
2141 if (xmlStrEqual(attrVal, BAD_CAST "optional"))
2142 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2143 else if (xmlStrEqual(attrVal, BAD_CAST "prohibited"))
2144 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
2145 else if (xmlStrEqual(attrVal, BAD_CAST "required"))
2146 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
2147 else
2148 xmlSchemaPErr(ctxt, node,
2149 XML_SCHEMAP_INVALID_ATTR_USE,
2150 "Attribute declaration %s has an invalid "
2151 "value for \"use\"\n", name, NULL);
2152 } else
2153 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002154
William M. Bracke7091952004-05-11 15:09:58 +00002155
2156 if (xmlSchemaGetProp(ctxt, node, "default") != NULL) {
2157 /* 3.2.3 : 1
2158 * default and fixed must not both be present.
2159 */
2160 if (xmlSchemaGetProp(ctxt, node, "fixed") != NULL) {
2161 xmlSchemaPErr(ctxt, node,
2162 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2163 "Attribute declaration has both, \"default\" "
2164 "and \"fixed\"\n", NULL, NULL);
2165 }
2166 /* 3.2.3 : 2
2167 * If default and use are both present, use must have
2168 * the actual value optional.
2169 */
2170 if (ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) {
2171 xmlSchemaPErr(ctxt, node,
2172 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2173 "Attribute declaration has \"default\" but "
2174 "\"use\" is not \"optional\"\n", NULL, NULL);
2175 }
2176 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002177
Daniel Veillard4255d502002-04-16 15:50:10 +00002178 ret->ref = ref;
2179 ret->refNs = refNs;
William M. Bracke7091952004-05-11 15:09:58 +00002180 /*
2181 * The setting of XML_SCHEMAS_ATTR_NSDEFAULT is not needed anymore,
2182 * since the target namespace was already evaluated and took
2183 * attributeFormDefault into account.
2184 */
2185 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002186 if ((ret->targetNamespace != NULL) &&
2187 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2188 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2189 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
William M. Bracke7091952004-05-11 15:09:58 +00002190 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002191 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
William M. Bracke7091952004-05-11 15:09:58 +00002192 if (ret->typeName != NULL)
2193 hasRefType = 1;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002194 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002195 child = node->children;
2196 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002197 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2198 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002199 }
2200 if (IS_SCHEMA(child, "simpleType")) {
William M. Bracke7091952004-05-11 15:09:58 +00002201 if (hasRefType) {
2202 /* 3.2.3 : 4
2203 * type and <simpleType> must not both be present.
2204 *
2205 * TODO: XML_SCHEMAP_INVALID_ATTR_COMBINATION seems not to be
2206 * a proper error type here.
2207 */
2208 xmlSchemaPErr2(ctxt, node, child,
2209 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2210 "Attribute declaration %s has both (\"ref\" or "
2211 "\"type\") and <simpleType>\n", name, NULL);
2212 } else
2213 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002214 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002215 }
2216 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002217 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2218 "attribute %s has unexpected content\n", name,
2219 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002220 }
2221
2222 return (ret);
2223}
2224
2225/**
2226 * xmlSchemaParseAttributeGroup:
2227 * @ctxt: a schema validation context
2228 * @schema: the schema being built
2229 * @node: a subtree containing XML Schema informations
2230 *
2231 * parse a XML schema Attribute Group declaration
2232 * *WARNING* this interface is highly subject to change
2233 *
2234 * Returns the attribute group or NULL in case of error.
2235 */
2236static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002237xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
2238 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002239{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002240 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002241 xmlSchemaAttributeGroupPtr ret;
2242 xmlSchemaAttributePtr last = NULL, attr;
2243 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002244 const xmlChar *oldcontainer;
2245 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002246
2247 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2248 return (NULL);
2249 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002250 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002251 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002252
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002253 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2254 if (ref == NULL) {
2255 xmlSchemaPErr2(ctxt, node, child,
2256 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2257 "AttributeGroup has no name nor ref\n", NULL,
2258 NULL);
2259 return (NULL);
2260 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002261 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2262 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002263 if (name == NULL) {
2264 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2265 return (NULL);
2266 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002267 }
2268 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2269 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002270 return (NULL);
2271 }
2272 ret->ref = ref;
2273 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002274 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002275 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002276 child = node->children;
2277 ctxt->container = name;
2278 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002279 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2280 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002281 }
2282 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002283 (IS_SCHEMA(child, "attributeGroup"))) {
2284 attr = NULL;
2285 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00002286 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002287 } else if (IS_SCHEMA(child, "attributeGroup")) {
2288 attr = (xmlSchemaAttributePtr)
2289 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2290 }
2291 if (attr != NULL) {
2292 if (last == NULL) {
2293 ret->attributes = attr;
2294 last = attr;
2295 } else {
2296 last->next = attr;
2297 last = attr;
2298 }
2299 }
2300 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002301 }
2302 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002303 TODO
2304 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002305 }
2306 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002307 xmlSchemaPErr2(ctxt, node, child,
2308 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2309 "attribute group %s has unexpected content\n", name,
2310 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002311 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002312 ctxt->container = oldcontainer;
2313 return (ret);
2314}
2315
2316/**
2317 * xmlSchemaParseElement:
2318 * @ctxt: a schema validation context
2319 * @schema: the schema being built
2320 * @node: a subtree containing XML Schema informations
2321 *
2322 * parse a XML schema Element declaration
2323 * *WARNING* this interface is highly subject to change
2324 *
William M. Bracke7091952004-05-11 15:09:58 +00002325 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002326 */
2327static xmlSchemaElementPtr
2328xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2329 xmlNodePtr node, int toplevel)
2330{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002331 const xmlChar *name, *fixed;
2332 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002333 xmlSchemaElementPtr ret;
2334 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002335 const xmlChar *oldcontainer;
2336 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002337 xmlAttrPtr attr;
2338
2339 /* 3.3.3 Constraints on XML Representations of Element Declarations */
2340 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002341
2342 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2343 return (NULL);
2344 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002345 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002346 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002347
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002348 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002349 /* 3.3.3 : 2.1
2350 * One of ref or name must be present, but not both
2351 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002352 if (ref == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00002353 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002354 XML_SCHEMAP_ELEM_NONAME_NOREF,
2355 "Element has no name nor ref\n", NULL, NULL);
2356 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002357 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002358 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2359 name = (const xmlChar *) buf;
2360 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2361 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002362 const xmlChar *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002363
William M. Bracke7091952004-05-11 15:09:58 +00002364 /* Evaluate the target namespace */
2365 if (schema->targetNamespace != NULL) {
2366 if (toplevel) {
2367 ns = schema->targetNamespace;
2368 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2369 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2370 BAD_CAST "qualified")) {
2371 ns = schema->targetNamespace;
2372 }
2373 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2374 ns = schema->targetNamespace;
2375 }
2376 }
2377 /*local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2378 ret = xmlSchemaAddElement(ctxt, schema, name, ns);
2379 /* 3.3.3 : 2.1
2380 * One of ref or name must be present, but not both
2381 */
2382 if ((!toplevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2383 xmlSchemaPErr(ctxt, node,
2384 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2385 "Element declaration has both, \"name\" and "
2386 "\"ref\"\n", NULL, NULL);
2387 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002388 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002389 if (ret != NULL)
2390 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002391 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002392 return (NULL);
2393 }
2394 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2395 ret->ref = ref;
2396 ret->refNs = refNs;
2397 if (ref != NULL)
2398 ret->flags |= XML_SCHEMAS_ELEM_REF;
William M. Bracke7091952004-05-11 15:09:58 +00002399
2400 /* 3.3.3 : 2.2 */
2401 if ((!toplevel) && (ref != NULL)) {
2402 attr = node->properties;
2403 while (attr != NULL) {
2404 if ((attr->ns == NULL) &&
2405 (!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
2406 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
2407 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
2408 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
2409
2410 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2411 "Element declaration %s: only minOccurs, maxOccurs "
2412 "and id are allowed in addition to ref\n",
2413 ret->name, NULL);
2414 }
2415 attr = attr->next;
2416 }
2417 }
2418
Daniel Veillard4255d502002-04-16 15:50:10 +00002419 if (toplevel)
2420 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2421 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2422 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2423 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2424 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2425 ctxt->container = name;
2426
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002427 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002428 ret->namedType =
William M. Bracke7091952004-05-11 15:09:58 +00002429 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002430 ret->substGroup =
2431 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2432 &(ret->substGroupNs));
William M. Bracke7091952004-05-11 15:09:58 +00002433 if ((ret->substGroup != NULL) && (!toplevel)) {
2434 /* 3.3.6 : 3 */
2435 /*
2436 * TODO: This seems to be redundant, since the schema for schemas
2437 * already prohibits the use of the "substitutionGroup" attribute
2438 * in local element declarations.
2439 */
2440 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2441 "Element declaration %s: substitutionGroup is allowed "
2442 "on top-level declarations only\n", ret->name, NULL);
2443
2444 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002445 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002446 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2447 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002448
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002449 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002450 if ((ret->value != NULL) && (fixed != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00002451 /* 3.3.3 : 1
2452 * default and fixed must not both be present.
2453 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002454 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2455 "Element %s has both default and fixed\n",
2456 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002457 } else if (fixed != NULL) {
2458 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002459 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002460 }
2461
2462 child = node->children;
2463 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002464 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2465 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002466 }
William M. Bracke7091952004-05-11 15:09:58 +00002467 if (ref != NULL) {
2468 /* 3.3.3 (2.2) */
2469 while (child != NULL) {
2470 if ((IS_SCHEMA(child, "complexType")) ||
2471 (IS_SCHEMA(child, "simpleType")) ||
2472 (IS_SCHEMA(child, "unique")) ||
2473 (IS_SCHEMA(child, "key")) ||
2474 (IS_SCHEMA(child, "keyref"))) {
2475
2476 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_REF_AND_CONTENT,
2477 "Element declaration %s: only annotation is "
2478 "allowed as content in addition to ref\n",
2479 ret->name, NULL);
2480 } else {
2481 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2482 "element %s has unexpected content\n", name, NULL);
2483 }
2484 child = child->next;
2485 }
2486 } else {
2487 if (IS_SCHEMA(child, "complexType")) {
2488 /* 3.3.3 : 3
2489 * type and either <simpleType> or <complexType> are mutually
2490 * exclusive
2491 */
2492 if (ret->namedType != NULL) {
2493 xmlSchemaPErr2(ctxt, node, child,
2494 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2495 "Element declaration %s has both \"type\" "
2496 "and a local complex type\n",
2497 ret->name, NULL);
2498 } else
2499 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
2500 child = child->next;
2501 } else if (IS_SCHEMA(child, "simpleType")) {
2502 /* 3.3.3 : 3
2503 * type and either <simpleType> or <complexType> are
2504 * mutually exclusive
2505 */
2506 if (ret->namedType != NULL) {
2507 xmlSchemaPErr2(ctxt, node, child,
2508 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2509 "Element declaration %s has both \"type\" "
2510 "and a local simple type\n",
2511 ret->name, NULL);
2512 } else
2513 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2514 child = child->next;
2515 }
2516
2517 while ((IS_SCHEMA(child, "unique")) ||
2518 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2519 TODO child = child->next;
2520 }
2521 if (child != NULL) {
2522 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2523 "element %s has unexpected content\n", name, NULL);
2524 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002525 }
2526
2527 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002528 return (ret);
2529}
2530
2531/**
2532 * xmlSchemaParseUnion:
2533 * @ctxt: a schema validation context
2534 * @schema: the schema being built
2535 * @node: a subtree containing XML Schema informations
2536 *
2537 * parse a XML schema Union definition
2538 * *WARNING* this interface is highly subject to change
2539 *
William M. Bracke7091952004-05-11 15:09:58 +00002540 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002541 * 1 in case of success.
2542 */
2543static xmlSchemaTypePtr
2544xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002545 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002546{
2547 xmlSchemaTypePtr type, subtype, last = NULL;
2548 xmlNodePtr child = NULL;
2549 xmlChar name[30];
2550
2551 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2552 return (NULL);
2553
2554
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002555 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002556 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002557 if (type == NULL)
2558 return (NULL);
2559 type->node = node;
Daniel Veillard377e1a92004-04-16 16:30:05 +00002560 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002561 type->id = xmlSchemaGetProp(ctxt, node, "id");
2562 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002563
2564 child = node->children;
2565 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002566 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2567 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002568 }
2569 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002570 subtype = (xmlSchemaTypePtr)
2571 xmlSchemaParseSimpleType(ctxt, schema, child);
2572 if (subtype != NULL) {
2573 if (last == NULL) {
2574 type->subtypes = subtype;
2575 last = subtype;
2576 } else {
2577 last->next = subtype;
2578 last = subtype;
2579 }
2580 last->next = NULL;
2581 }
2582 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002583 }
2584 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002585 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2586 "Union %s has unexpected content\n", type->name,
2587 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002588 }
2589 return (type);
2590}
2591
2592/**
2593 * xmlSchemaParseList:
2594 * @ctxt: a schema validation context
2595 * @schema: the schema being built
2596 * @node: a subtree containing XML Schema informations
2597 *
2598 * parse a XML schema List definition
2599 * *WARNING* this interface is highly subject to change
2600 *
William M. Bracke7091952004-05-11 15:09:58 +00002601 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002602 * 1 in case of success.
2603 */
2604static xmlSchemaTypePtr
2605xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002606 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002607{
2608 xmlSchemaTypePtr type, subtype;
2609 xmlNodePtr child = NULL;
2610 xmlChar name[30];
2611
2612 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2613 return (NULL);
2614
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002615 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002616 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002617 if (type == NULL)
2618 return (NULL);
2619 type->node = node;
2620 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002621 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002622 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2623
2624 child = node->children;
2625 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002626 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2627 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002628 }
William M. Bracke7091952004-05-11 15:09:58 +00002629
Daniel Veillard4255d502002-04-16 15:50:10 +00002630 subtype = NULL;
2631 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002632 subtype = (xmlSchemaTypePtr)
2633 xmlSchemaParseSimpleType(ctxt, schema, child);
2634 child = child->next;
2635 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002636 }
2637 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002638 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2639 "List %s has unexpected content\n", type->name,
2640 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002641 }
2642 return (type);
2643}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002644
Daniel Veillard4255d502002-04-16 15:50:10 +00002645/**
2646 * xmlSchemaParseSimpleType:
2647 * @ctxt: a schema validation context
2648 * @schema: the schema being built
2649 * @node: a subtree containing XML Schema informations
2650 *
2651 * parse a XML schema Simple Type definition
2652 * *WARNING* this interface is highly subject to change
2653 *
William M. Bracke7091952004-05-11 15:09:58 +00002654 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002655 * 1 in case of success.
2656 */
2657static xmlSchemaTypePtr
2658xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2659 xmlNodePtr node)
2660{
2661 xmlSchemaTypePtr type, subtype;
2662 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002663 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002664
2665 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2666 return (NULL);
2667
2668
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002669 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002670 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002671 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002672
William M. Bracke7091952004-05-11 15:09:58 +00002673 snprintf(buf, 99, "simpleType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002674 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002675 } else {
2676 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2677 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002678 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002679 if (type == NULL)
2680 return (NULL);
2681 type->node = node;
2682 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002683 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002684
2685 child = node->children;
2686 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002687 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2688 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002689 }
2690 subtype = NULL;
2691 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002692 subtype = (xmlSchemaTypePtr)
2693 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2694 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002695 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002696 subtype = (xmlSchemaTypePtr)
2697 xmlSchemaParseList(ctxt, schema, child);
2698 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002699 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002700 subtype = (xmlSchemaTypePtr)
2701 xmlSchemaParseUnion(ctxt, schema, child);
2702 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002703 }
2704 type->subtypes = subtype;
William M. Bracke7091952004-05-11 15:09:58 +00002705 if (subtype == NULL) {
2706 xmlSchemaPErr2(ctxt, node, child,
2707 XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD,
2708 "SimpleType %s does not define a variety\n",
2709 type->name, NULL);
2710 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002711 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002712 xmlSchemaPErr2(ctxt, node, child,
2713 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2714 "SimpleType %s has unexpected content\n",
2715 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002716 }
2717
2718 return (type);
2719}
2720
2721
2722/**
2723 * xmlSchemaParseGroup:
2724 * @ctxt: a schema validation context
2725 * @schema: the schema being built
2726 * @node: a subtree containing XML Schema informations
2727 *
2728 * parse a XML schema Group definition
2729 * *WARNING* this interface is highly subject to change
2730 *
William M. Bracke7091952004-05-11 15:09:58 +00002731 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002732 * 1 in case of success.
2733 */
2734static xmlSchemaTypePtr
2735xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002736 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002737{
2738 xmlSchemaTypePtr type, subtype;
2739 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002740 const xmlChar *name;
2741 const xmlChar *ref = NULL, *refNs = NULL;
2742 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002743
2744 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2745 return (NULL);
2746
2747
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002748 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002749 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002750
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002751 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2752 if (ref == NULL) {
2753 xmlSchemaPErr2(ctxt, node, child,
2754 XML_SCHEMAP_GROUP_NONAME_NOREF,
2755 "Group has no name nor ref\n", NULL, NULL);
2756 return (NULL);
2757 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002758 if (refNs == NULL)
2759 refNs = schema->targetNamespace;
2760 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2761 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00002762 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002763 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002764 if (type == NULL)
2765 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00002766
Daniel Veillard4255d502002-04-16 15:50:10 +00002767 type->node = node;
2768 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002769 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002770 type->ref = ref;
2771 type->refNs = refNs;
2772 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2773 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2774
2775 child = node->children;
2776 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002777 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2778 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002779 }
2780 subtype = NULL;
2781 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002782 subtype = (xmlSchemaTypePtr)
2783 xmlSchemaParseAll(ctxt, schema, child);
2784 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002785 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002786 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2787 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002788 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002789 subtype = (xmlSchemaTypePtr)
2790 xmlSchemaParseSequence(ctxt, schema, child);
2791 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002792 }
2793 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002794 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002795 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002796 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2797 "Group %s has unexpected content\n", type->name,
2798 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002799 }
2800
2801 return (type);
2802}
2803
2804/**
2805 * xmlSchemaParseAll:
2806 * @ctxt: a schema validation context
2807 * @schema: the schema being built
2808 * @node: a subtree containing XML Schema informations
2809 *
2810 * parse a XML schema All definition
2811 * *WARNING* this interface is highly subject to change
2812 *
William M. Bracke7091952004-05-11 15:09:58 +00002813 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002814 * 1 in case of success.
2815 */
2816static xmlSchemaTypePtr
2817xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002818 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002819{
2820 xmlSchemaTypePtr type, subtype, last = NULL;
2821 xmlNodePtr child = NULL;
2822 xmlChar name[30];
2823
2824 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2825 return (NULL);
2826
2827
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002828 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002829 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002830 if (type == NULL)
2831 return (NULL);
2832 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002833 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002834 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002835 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002836 if (type->minOccurs > 1)
2837 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2838 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002839 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002840 if (type->maxOccurs > 1)
2841 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2842 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002843
2844 child = node->children;
2845 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002846 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2847 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002848 }
2849 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002850 subtype = (xmlSchemaTypePtr)
2851 xmlSchemaParseElement(ctxt, schema, child, 0);
2852 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00002853 if (subtype->minOccurs > 1)
2854 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
2855 "invalid value for minOccurs (must be 0 or 1)\n",
2856 NULL, NULL);
2857 if (subtype->maxOccurs > 1)
2858 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
2859 "invalid value for maxOccurs (must be 0 or 1)\n",
2860 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002861 if (last == NULL) {
2862 type->subtypes = subtype;
2863 last = subtype;
2864 } else {
2865 last->next = subtype;
2866 last = subtype;
2867 }
2868 last->next = NULL;
2869 }
2870 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002871 }
2872 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002873 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2874 "All %s has unexpected content\n", type->name,
2875 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002876 }
2877
2878 return (type);
2879}
2880
2881/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002882 * xmlSchemaImportSchema
2883 *
2884 * @ctxt: a schema validation context
2885 * @schemaLocation: an URI defining where to find the imported schema
2886 *
2887 * import a XML schema
2888 * *WARNING* this interface is highly subject to change
2889 *
2890 * Returns -1 in case of error and 1 in case of success.
2891 */
2892static xmlSchemaImportPtr
2893xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2894 const xmlChar *schemaLocation)
2895{
2896 xmlSchemaImportPtr import;
2897 xmlSchemaParserCtxtPtr newctxt;
2898
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002899 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00002900 if (newctxt == NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002901 xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00002902 NULL);
2903 return (NULL);
2904 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002905 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
2906 /* Keep the same dictionnary for parsing, really */
2907 xmlDictReference(ctxt->dict);
2908 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002909 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002910 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
2911
Daniel Veillard1d913862003-11-21 00:28:39 +00002912 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2913 ctxt->userData);
2914
2915 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2916 if (import == NULL) {
2917 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2918 NULL);
2919 xmlSchemaFreeParserCtxt(newctxt);
2920 return (NULL);
2921 }
2922
2923 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002924 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00002925 import->schema = xmlSchemaParse(newctxt);
2926
2927 if (import->schema == NULL) {
2928 /* FIXME use another error enum here ? */
2929 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2930 "failed to import schema at location %s\n",
2931 schemaLocation, NULL);
2932
2933 xmlSchemaFreeParserCtxt(newctxt);
2934 if (import->schemaLocation != NULL)
2935 xmlFree((xmlChar *)import->schemaLocation);
2936 xmlFree(import);
2937 return NULL;
2938 }
2939
2940 xmlSchemaFreeParserCtxt(newctxt);
2941 return import;
2942}
2943
2944
2945/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002946 * xmlSchemaParseImport:
2947 * @ctxt: a schema validation context
2948 * @schema: the schema being built
2949 * @node: a subtree containing XML Schema informations
2950 *
2951 * parse a XML schema Import definition
2952 * *WARNING* this interface is highly subject to change
2953 *
William M. Bracke7091952004-05-11 15:09:58 +00002954 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard5a872412002-05-22 06:40:27 +00002955 * 1 in case of success.
2956 */
2957static int
2958xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002959 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002960{
2961 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00002962 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002963 const xmlChar *namespace;
2964 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00002965 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00002966 xmlURIPtr check;
2967
Daniel Veillard1d913862003-11-21 00:28:39 +00002968
Daniel Veillard5a872412002-05-22 06:40:27 +00002969 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2970 return (-1);
2971
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002972 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00002973 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002974 check = xmlParseURI((const char *) namespace);
2975 if (check == NULL) {
2976 xmlSchemaPErr2(ctxt, node, child,
2977 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2978 "Import namespace attribute is not an URI: %s\n",
2979 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002980 return (-1);
2981 } else {
2982 xmlFreeURI(check);
2983 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002984 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002985 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00002986 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002987 xmlChar *base = NULL;
2988 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002989 check = xmlParseURI((const char *) schemaLocation);
2990 if (check == NULL) {
2991 xmlSchemaPErr2(ctxt, node, child,
2992 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2993 "Import schemaLocation attribute is not an URI: %s\n",
2994 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002995 return (-1);
2996 } else {
2997 xmlFreeURI(check);
2998 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002999 base = xmlNodeGetBase(node->doc, node);
3000 if (base == NULL) {
3001 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3002 } else {
3003 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003004 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00003005 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003006 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003007 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3008 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00003009 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003010 }
3011 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003012 schema->schemasImports = xmlHashCreate(10);
3013 if (schema->schemasImports == NULL) {
3014 xmlSchemaPErr2(ctxt, node, child,
3015 XML_SCHEMAP_FAILED_BUILD_IMPORT,
3016 "Internal: failed to build import table\n",
3017 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003018 return (-1);
3019 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003020 }
3021 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003022 import = xmlHashLookup(schema->schemasImports,
3023 XML_SCHEMAS_DEFAULT_NAMESPACE);
3024 if (import != NULL)
3025 previous = import->schemaLocation;
3026 else
3027 previous = NULL;
3028
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003029 if (schemaLocation != NULL) {
3030 if (previous != NULL) {
3031 if (!xmlStrEqual(schemaLocation, previous)) {
3032 xmlSchemaPErr2(ctxt, node, child,
3033 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003034 "Redefining import for default namespace "
3035 "with a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003036 schemaLocation, NULL);
3037 }
3038 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003039 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3040 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003041 return (-1);
3042 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003043 xmlHashAddEntry(schema->schemasImports,
3044 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00003045 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003046 }
3047 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003048 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003049 import = xmlHashLookup(schema->schemasImports, namespace);
3050 if (import != NULL)
3051 previous = import->schemaLocation;
3052 else
3053 previous = NULL;
3054
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003055 if (schemaLocation != NULL) {
3056 if (previous != NULL) {
3057 if (!xmlStrEqual(schemaLocation, previous)) {
3058 xmlSchemaPErr2(ctxt, node, child,
3059 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003060 "Redefining import for namespace %s with "
3061 "a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003062 namespace, schemaLocation);
3063 }
3064 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003065 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3066 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003067 return (-1);
3068 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003069 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00003070 namespace, import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003071 }
3072 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003073 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003074
3075 child = node->children;
3076 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003077 /*
3078 * the annotations here are simply discarded ...
3079 */
3080 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00003081 }
3082 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003083 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
3084 "Import has unexpected content\n", NULL, NULL);
3085 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003086 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003087 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003088}
3089
3090/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003091 * xmlSchemaCleanupDoc:
3092 * @ctxt: a schema validation context
3093 * @node: the root of the document.
3094 *
3095 * removes unwanted nodes in a schemas document tree
3096 */
3097static void
3098xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
3099{
3100 xmlNodePtr delete, cur;
3101
3102 if ((ctxt == NULL) || (root == NULL)) return;
3103
3104 /*
3105 * Remove all the blank text nodes
3106 */
3107 delete = NULL;
3108 cur = root;
3109 while (cur != NULL) {
3110 if (delete != NULL) {
3111 xmlUnlinkNode(delete);
3112 xmlFreeNode(delete);
3113 delete = NULL;
3114 }
3115 if (cur->type == XML_TEXT_NODE) {
3116 if (IS_BLANK_NODE(cur)) {
3117 if (xmlNodeGetSpacePreserve(cur) != 1) {
3118 delete = cur;
3119 }
3120 }
3121 } else if ((cur->type != XML_ELEMENT_NODE) &&
3122 (cur->type != XML_CDATA_SECTION_NODE)) {
3123 delete = cur;
3124 goto skip_children;
3125 }
3126
3127 /*
3128 * Skip to next node
3129 */
3130 if (cur->children != NULL) {
3131 if ((cur->children->type != XML_ENTITY_DECL) &&
3132 (cur->children->type != XML_ENTITY_REF_NODE) &&
3133 (cur->children->type != XML_ENTITY_NODE)) {
3134 cur = cur->children;
3135 continue;
3136 }
3137 }
3138 skip_children:
3139 if (cur->next != NULL) {
3140 cur = cur->next;
3141 continue;
3142 }
3143
3144 do {
3145 cur = cur->parent;
3146 if (cur == NULL)
3147 break;
3148 if (cur == root) {
3149 cur = NULL;
3150 break;
3151 }
3152 if (cur->next != NULL) {
3153 cur = cur->next;
3154 break;
3155 }
3156 } while (cur != NULL);
3157 }
3158 if (delete != NULL) {
3159 xmlUnlinkNode(delete);
3160 xmlFreeNode(delete);
3161 delete = NULL;
3162 }
3163}
3164
3165/**
3166 * xmlSchemaParseSchemaTopLevel:
3167 * @ctxt: a schema validation context
3168 * @schema: the schemas
3169 * @nodes: the list of top level nodes
3170 *
3171 * Returns the internal XML Schema structure built from the resource or
3172 * NULL in case of error
3173 */
3174static void
3175xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
3176 xmlSchemaPtr schema, xmlNodePtr nodes)
3177{
3178 xmlNodePtr child;
3179 xmlSchemaAnnotPtr annot;
3180
3181 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
3182 return;
3183
3184 child = nodes;
3185 while ((IS_SCHEMA(child, "include")) ||
3186 (IS_SCHEMA(child, "import")) ||
3187 (IS_SCHEMA(child, "redefine")) ||
3188 (IS_SCHEMA(child, "annotation"))) {
3189 if (IS_SCHEMA(child, "annotation")) {
3190 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3191 if (schema->annot == NULL)
3192 schema->annot = annot;
3193 else
3194 xmlSchemaFreeAnnot(annot);
3195 } else if (IS_SCHEMA(child, "import")) {
3196 xmlSchemaParseImport(ctxt, schema, child);
3197 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003198 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003199 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003200 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003201 } else if (IS_SCHEMA(child, "redefine")) {
3202 TODO
3203 }
3204 child = child->next;
3205 }
3206 while (child != NULL) {
3207 if (IS_SCHEMA(child, "complexType")) {
3208 xmlSchemaParseComplexType(ctxt, schema, child);
3209 child = child->next;
3210 } else if (IS_SCHEMA(child, "simpleType")) {
3211 xmlSchemaParseSimpleType(ctxt, schema, child);
3212 child = child->next;
3213 } else if (IS_SCHEMA(child, "element")) {
3214 xmlSchemaParseElement(ctxt, schema, child, 1);
3215 child = child->next;
3216 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003217 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003218 child = child->next;
3219 } else if (IS_SCHEMA(child, "attributeGroup")) {
3220 xmlSchemaParseAttributeGroup(ctxt, schema, child);
3221 child = child->next;
3222 } else if (IS_SCHEMA(child, "group")) {
3223 xmlSchemaParseGroup(ctxt, schema, child);
3224 child = child->next;
3225 } else if (IS_SCHEMA(child, "notation")) {
3226 xmlSchemaParseNotation(ctxt, schema, child);
3227 child = child->next;
3228 } else {
3229 xmlSchemaPErr2(ctxt, NULL, child,
3230 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3231 "Schemas: unexpected element %s here \n",
3232 child->name, NULL);
3233 child = child->next;
3234 }
3235 while (IS_SCHEMA(child, "annotation")) {
3236 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3237 if (schema->annot == NULL)
3238 schema->annot = annot;
3239 else
3240 xmlSchemaFreeAnnot(annot);
3241 child = child->next;
3242 }
3243 }
3244}
3245
3246/**
3247 * xmlSchemaParseInclude:
3248 * @ctxt: a schema validation context
3249 * @schema: the schema being built
3250 * @node: a subtree containing XML Schema informations
3251 *
3252 * parse a XML schema Include definition
3253 *
William M. Bracke7091952004-05-11 15:09:58 +00003254 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003255 * 1 in case of success.
3256 */
3257static int
3258xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3259 xmlNodePtr node)
3260{
3261 xmlNodePtr child = NULL;
3262 const xmlChar *schemaLocation;
3263 xmlURIPtr check;
3264 xmlDocPtr doc;
3265 xmlNodePtr root;
3266 xmlSchemaIncludePtr include;
3267
3268
3269 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3270 return (-1);
3271
3272 /*
3273 * Preliminary step, extract the URI-Reference for the include and
3274 * make an URI from the base.
3275 */
3276 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
3277 if (schemaLocation != NULL) {
3278 xmlChar *base = NULL;
3279 xmlChar *URI = NULL;
3280 check = xmlParseURI((const char *) schemaLocation);
3281 if (check == NULL) {
3282 xmlSchemaPErr2(ctxt, node, child,
3283 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3284 "Include schemaLocation attribute is not an URI: %s\n",
3285 schemaLocation, NULL);
3286 return (-1);
3287 } else {
3288 xmlFreeURI(check);
3289 }
3290 base = xmlNodeGetBase(node->doc, node);
3291 if (base == NULL) {
3292 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3293 } else {
3294 URI = xmlBuildURI(schemaLocation, base);
3295 xmlFree(base);
3296 }
3297 if (URI != NULL) {
3298 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3299 xmlFree(URI);
3300 }
3301 } else {
3302 xmlSchemaPErr2(ctxt, node, child,
3303 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3304 "Include schemaLocation attribute missing\n",
3305 NULL, NULL);
3306 return (-1);
3307 }
3308
3309 child = node->children;
3310 while (IS_SCHEMA(child, "annotation")) {
3311 /*
3312 * the annotations here are simply discarded ...
3313 */
3314 child = child->next;
3315 }
3316 if (child != NULL) {
3317 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3318 "Include has unexpected content\n", NULL, NULL);
3319 return (-1);
3320 }
3321
3322 /*
3323 * First step is to parse the input document into an DOM/Infoset
3324 */
3325 doc = xmlReadFile((const char *) schemaLocation, NULL,
3326 SCHEMAS_PARSE_OPTIONS);
3327 if (doc == NULL) {
3328 xmlSchemaPErr(ctxt, NULL,
3329 XML_SCHEMAP_FAILED_LOAD,
3330 "xmlSchemaParse: could not load %s\n",
3331 ctxt->URL, NULL);
3332 return(-1);
3333 }
3334
3335 /*
3336 * Then extract the root of the schema
3337 */
3338 root = xmlDocGetRootElement(doc);
3339 if (root == NULL) {
3340 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3341 XML_SCHEMAP_NOROOT,
3342 "schemas %s has no root", schemaLocation, NULL);
3343 xmlFreeDoc(doc);
3344 return (-1);
3345 }
3346
3347 /*
3348 * Remove all the blank text nodes
3349 */
3350 xmlSchemaCleanupDoc(ctxt, root);
3351
3352 /*
3353 * Check the schemas top level element
3354 */
3355 if (!IS_SCHEMA(root, "schema")) {
3356 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3357 XML_SCHEMAP_NOT_SCHEMA,
3358 "File %s is not a schemas", schemaLocation, NULL);
3359 xmlFreeDoc(doc);
3360 return (-1);
3361 }
3362
3363 /*
3364 * register the include
3365 */
3366 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3367 if (include == NULL) {
3368 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3369 xmlFreeDoc(doc);
3370 return (-1);
3371 }
3372
3373 memset(include, 0, sizeof(xmlSchemaInclude));
3374 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3375 include->doc = doc;
3376 include->next = schema->includes;
3377 schema->includes = include;
3378
3379
3380 /*
3381 * parse the declarations in the included file like if they
3382 * were in the original file.
3383 */
3384 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3385
3386 return (1);
3387}
3388
3389/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003390 * xmlSchemaParseChoice:
3391 * @ctxt: a schema validation context
3392 * @schema: the schema being built
3393 * @node: a subtree containing XML Schema informations
3394 *
3395 * parse a XML schema Choice definition
3396 * *WARNING* this interface is highly subject to change
3397 *
William M. Bracke7091952004-05-11 15:09:58 +00003398 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003399 * 1 in case of success.
3400 */
3401static xmlSchemaTypePtr
3402xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003403 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003404{
3405 xmlSchemaTypePtr type, subtype, last = NULL;
3406 xmlNodePtr child = NULL;
3407 xmlChar name[30];
3408
3409 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3410 return (NULL);
3411
3412
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003413 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003414 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003415 if (type == NULL)
3416 return (NULL);
3417 type->node = node;
3418 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003419 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003420 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3421 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3422
3423 child = node->children;
3424 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003425 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3426 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003427 }
3428 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003429 (IS_SCHEMA(child, "group")) ||
3430 (IS_SCHEMA(child, "any")) ||
3431 (IS_SCHEMA(child, "choice")) ||
3432 (IS_SCHEMA(child, "sequence"))) {
3433 subtype = NULL;
3434 if (IS_SCHEMA(child, "element")) {
3435 subtype = (xmlSchemaTypePtr)
3436 xmlSchemaParseElement(ctxt, schema, child, 0);
3437 } else if (IS_SCHEMA(child, "group")) {
3438 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3439 } else if (IS_SCHEMA(child, "any")) {
3440 subtype = xmlSchemaParseAny(ctxt, schema, child);
3441 } else if (IS_SCHEMA(child, "sequence")) {
3442 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3443 } else if (IS_SCHEMA(child, "choice")) {
3444 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3445 }
3446 if (subtype != NULL) {
3447 if (last == NULL) {
3448 type->subtypes = subtype;
3449 last = subtype;
3450 } else {
3451 last->next = subtype;
3452 last = subtype;
3453 }
3454 last->next = NULL;
3455 }
3456 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003457 }
3458 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003459 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3460 "Choice %s has unexpected content\n", type->name,
3461 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003462 }
3463
3464 return (type);
3465}
3466
3467/**
3468 * xmlSchemaParseSequence:
3469 * @ctxt: a schema validation context
3470 * @schema: the schema being built
3471 * @node: a subtree containing XML Schema informations
3472 *
3473 * parse a XML schema Sequence definition
3474 * *WARNING* this interface is highly subject to change
3475 *
William M. Bracke7091952004-05-11 15:09:58 +00003476 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003477 * 1 in case of success.
3478 */
3479static xmlSchemaTypePtr
3480xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003481 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003482{
3483 xmlSchemaTypePtr type, subtype, last = NULL;
3484 xmlNodePtr child = NULL;
3485 xmlChar name[30];
3486
3487 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3488 return (NULL);
3489
3490
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003491 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003492 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003493 if (type == NULL)
3494 return (NULL);
3495 type->node = node;
3496 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003497 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003498 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3499 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3500
3501 child = node->children;
3502 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003503 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3504 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003505 }
3506 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003507 (IS_SCHEMA(child, "group")) ||
3508 (IS_SCHEMA(child, "any")) ||
3509 (IS_SCHEMA(child, "choice")) ||
3510 (IS_SCHEMA(child, "sequence"))) {
3511 subtype = NULL;
3512 if (IS_SCHEMA(child, "element")) {
3513 subtype = (xmlSchemaTypePtr)
3514 xmlSchemaParseElement(ctxt, schema, child, 0);
3515 } else if (IS_SCHEMA(child, "group")) {
3516 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3517 } else if (IS_SCHEMA(child, "any")) {
3518 subtype = xmlSchemaParseAny(ctxt, schema, child);
3519 } else if (IS_SCHEMA(child, "choice")) {
3520 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3521 } else if (IS_SCHEMA(child, "sequence")) {
3522 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3523 }
3524 if (subtype != NULL) {
3525 if (last == NULL) {
3526 type->subtypes = subtype;
3527 last = subtype;
3528 } else {
3529 last->next = subtype;
3530 last = subtype;
3531 }
3532 last->next = NULL;
3533 }
3534 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003535 }
3536 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003537 xmlSchemaPErr2(ctxt, node, child,
3538 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3539 "Sequence %s has unexpected content\n", type->name,
3540 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003541 }
3542
3543 return (type);
3544}
3545
3546/**
3547 * xmlSchemaParseRestriction:
3548 * @ctxt: a schema validation context
3549 * @schema: the schema being built
3550 * @node: a subtree containing XML Schema informations
3551 * @simple: is that part of a simple type.
3552 *
3553 * parse a XML schema Restriction definition
3554 * *WARNING* this interface is highly subject to change
3555 *
3556 * Returns the type definition or NULL in case of error
3557 */
3558static xmlSchemaTypePtr
3559xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3560 xmlNodePtr node, int simple)
3561{
3562 xmlSchemaTypePtr type, subtype;
3563 xmlSchemaFacetPtr facet, lastfacet = NULL;
3564 xmlNodePtr child = NULL;
3565 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003566 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003567
3568 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3569 return (NULL);
3570
3571 oldcontainer = ctxt->container;
3572
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003573 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003574 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003575 if (type == NULL)
3576 return (NULL);
3577 type->node = node;
3578 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003579 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003580 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3581 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003582 xmlSchemaPErr2(ctxt, node, child,
3583 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
3584 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003585 }
3586 ctxt->container = name;
3587
3588 child = node->children;
3589 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003590 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3591 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003592 }
3593 subtype = NULL;
3594
3595 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003596 subtype = (xmlSchemaTypePtr)
3597 xmlSchemaParseAll(ctxt, schema, child);
3598 child = child->next;
3599 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003600 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003601 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3602 child = child->next;
3603 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003604 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003605 subtype = (xmlSchemaTypePtr)
3606 xmlSchemaParseSequence(ctxt, schema, child);
3607 child = child->next;
3608 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003609 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003610 subtype = (xmlSchemaTypePtr)
3611 xmlSchemaParseGroup(ctxt, schema, child);
3612 child = child->next;
3613 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003615 if (IS_SCHEMA(child, "simpleType")) {
3616 subtype = (xmlSchemaTypePtr)
3617 xmlSchemaParseSimpleType(ctxt, schema, child);
3618 child = child->next;
3619 type->baseType = subtype;
3620 }
3621 /*
3622 * Facets
3623 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003624 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003625 (IS_SCHEMA(child, "minExclusive")) ||
3626 (IS_SCHEMA(child, "maxInclusive")) ||
3627 (IS_SCHEMA(child, "maxExclusive")) ||
3628 (IS_SCHEMA(child, "totalDigits")) ||
3629 (IS_SCHEMA(child, "fractionDigits")) ||
3630 (IS_SCHEMA(child, "pattern")) ||
3631 (IS_SCHEMA(child, "enumeration")) ||
3632 (IS_SCHEMA(child, "whiteSpace")) ||
3633 (IS_SCHEMA(child, "length")) ||
3634 (IS_SCHEMA(child, "maxLength")) ||
3635 (IS_SCHEMA(child, "minLength"))) {
3636 facet = xmlSchemaParseFacet(ctxt, schema, child);
3637 if (facet != NULL) {
3638 if (lastfacet == NULL) {
3639 type->facets = facet;
3640 lastfacet = facet;
3641 } else {
3642 lastfacet->next = facet;
3643 lastfacet = facet;
3644 }
3645 lastfacet->next = NULL;
3646 }
3647 child = child->next;
3648 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003649 }
3650 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3651 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003652 xmlSchemaPErr2(ctxt, node, child,
3653 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
3654 "Restriction %s has unexpected content\n",
3655 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003656 }
3657 ctxt->container = oldcontainer;
3658 return (type);
3659}
3660
3661/**
3662 * xmlSchemaParseExtension:
3663 * @ctxt: a schema validation context
3664 * @schema: the schema being built
3665 * @node: a subtree containing XML Schema informations
3666 *
3667 * parse a XML schema Extension definition
3668 * *WARNING* this interface is highly subject to change
3669 *
3670 * Returns the type definition or NULL in case of error
3671 */
3672static xmlSchemaTypePtr
3673xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003674 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003675{
3676 xmlSchemaTypePtr type, subtype;
3677 xmlNodePtr child = NULL;
3678 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003679 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003680
3681 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3682 return (NULL);
3683
3684 oldcontainer = ctxt->container;
3685
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003686 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003687 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003688 if (type == NULL)
3689 return (NULL);
3690 type->node = node;
3691 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003692 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003693 ctxt->container = name;
3694
3695 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3696 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003697 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3698 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003699 }
3700 child = node->children;
3701 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003702 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3703 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003704 }
3705 subtype = NULL;
3706
3707 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003708 subtype = xmlSchemaParseAll(ctxt, schema, child);
3709 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003710 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003711 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3712 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003713 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003714 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3715 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003716 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003717 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3718 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003719 }
3720 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003721 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003722 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3723 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003724 xmlSchemaPErr2(ctxt, node, child,
3725 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3726 "Extension %s has unexpected content\n", type->name,
3727 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003728 }
3729 ctxt->container = oldcontainer;
3730 return (type);
3731}
3732
3733/**
3734 * xmlSchemaParseSimpleContent:
3735 * @ctxt: a schema validation context
3736 * @schema: the schema being built
3737 * @node: a subtree containing XML Schema informations
3738 *
3739 * parse a XML schema SimpleContent definition
3740 * *WARNING* this interface is highly subject to change
3741 *
3742 * Returns the type definition or NULL in case of error
3743 */
3744static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003745xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3746 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003747{
3748 xmlSchemaTypePtr type, subtype;
3749 xmlNodePtr child = NULL;
3750 xmlChar name[30];
3751
3752 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3753 return (NULL);
3754
3755
William M. Bracke7091952004-05-11 15:09:58 +00003756 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003757 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003758 if (type == NULL)
3759 return (NULL);
3760 type->node = node;
3761 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003762 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003763
3764 child = node->children;
3765 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003766 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3767 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003768 }
3769 subtype = NULL;
3770 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003771 subtype = (xmlSchemaTypePtr)
3772 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3773 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003774 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003775 subtype = (xmlSchemaTypePtr)
3776 xmlSchemaParseExtension(ctxt, schema, child);
3777 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003778 }
3779 type->subtypes = subtype;
3780 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003781 xmlSchemaPErr2(ctxt, node, child,
3782 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3783 "SimpleContent %s has unexpected content\n",
3784 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003785 }
3786 return (type);
3787}
3788
3789/**
3790 * xmlSchemaParseComplexContent:
3791 * @ctxt: a schema validation context
3792 * @schema: the schema being built
3793 * @node: a subtree containing XML Schema informations
3794 *
3795 * parse a XML schema ComplexContent definition
3796 * *WARNING* this interface is highly subject to change
3797 *
3798 * Returns the type definition or NULL in case of error
3799 */
3800static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003801xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3802 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003803{
3804 xmlSchemaTypePtr type, subtype;
3805 xmlNodePtr child = NULL;
3806 xmlChar name[30];
3807
3808 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3809 return (NULL);
3810
3811
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003812 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003813 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003814 if (type == NULL)
3815 return (NULL);
3816 type->node = node;
3817 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003818 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003819
3820 child = node->children;
3821 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003822 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3823 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003824 }
3825 subtype = NULL;
3826 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003827 subtype = (xmlSchemaTypePtr)
3828 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3829 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003830 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003831 subtype = (xmlSchemaTypePtr)
3832 xmlSchemaParseExtension(ctxt, schema, child);
3833 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003834 }
3835 type->subtypes = subtype;
3836 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003837 xmlSchemaPErr2(ctxt, node, child,
3838 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3839 "ComplexContent %s has unexpected content\n",
3840 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003841 }
3842 return (type);
3843}
3844
3845/**
3846 * xmlSchemaParseComplexType:
3847 * @ctxt: a schema validation context
3848 * @schema: the schema being built
3849 * @node: a subtree containing XML Schema informations
3850 *
3851 * parse a XML schema Complex Type definition
3852 * *WARNING* this interface is highly subject to change
3853 *
3854 * Returns the type definition or NULL in case of error
3855 */
3856static xmlSchemaTypePtr
3857xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3858 xmlNodePtr node)
3859{
3860 xmlSchemaTypePtr type, subtype;
3861 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003862 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00003863 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003864 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003865
3866 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3867 return (NULL);
3868
3869 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003870 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003871 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003872
William M. Bracke7091952004-05-11 15:09:58 +00003873 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003874 name = (const xmlChar *)buf;
3875 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3876 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003877
William M. Bracke7091952004-05-11 15:09:58 +00003878 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
3879 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003880 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003881 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003882 return (NULL);
3883 }
Daniel Veillard1aefc862004-03-04 11:40:48 +00003884
William M. Bracke7091952004-05-11 15:09:58 +00003885 if (xmlGetBooleanProp(ctxt, node, "mixed", 0))
3886 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00003887
Daniel Veillard4255d502002-04-16 15:50:10 +00003888 type->node = node;
3889 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003890 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003891 ctxt->container = name;
3892
3893 child = node->children;
3894 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003895 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3896 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003897 }
3898 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00003899 /* 3.4.3 : 2.2
3900 * Specifying mixed='true' when the <simpleContent>
3901 * alternative is chosen has no effect
3902 */
3903 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
3904 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003905 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3906 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003907 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003908 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3909 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003910 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003911 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003912
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003913 if (IS_SCHEMA(child, "all")) {
3914 subtype = xmlSchemaParseAll(ctxt, schema, child);
3915 child = child->next;
3916 } else if (IS_SCHEMA(child, "choice")) {
3917 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3918 child = child->next;
3919 } else if (IS_SCHEMA(child, "sequence")) {
3920 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3921 child = child->next;
3922 } else if (IS_SCHEMA(child, "group")) {
3923 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3924 child = child->next;
3925 }
3926 if (subtype != NULL)
3927 type->subtypes = subtype;
3928 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003929 }
3930 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003931 xmlSchemaPErr2(ctxt, node, child,
3932 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3933 "ComplexType %s has unexpected content\n",
3934 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003935 }
3936 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003937 return (type);
3938}
3939
Daniel Veillard4255d502002-04-16 15:50:10 +00003940/**
3941 * xmlSchemaParseSchema:
3942 * @ctxt: a schema validation context
3943 * @node: a subtree containing XML Schema informations
3944 *
3945 * parse a XML schema definition from a node set
3946 * *WARNING* this interface is highly subject to change
3947 *
3948 * Returns the internal XML Schema structure built from the resource or
3949 * NULL in case of error
3950 */
3951static xmlSchemaPtr
3952xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3953{
3954 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003955 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003956 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003957 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003958
3959 if ((ctxt == NULL) || (node == NULL))
3960 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00003961
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003962 nberrors = ctxt->nberrors;
3963 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003964 if (IS_SCHEMA(node, "schema")) {
3965 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003966 if (schema == NULL)
3967 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003968 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3969 if (val != NULL) {
3970 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3971 } else {
3972 schema->targetNamespace = NULL;
3973 }
3974 schema->id = xmlSchemaGetProp(ctxt, node, "id");
3975 schema->version = xmlSchemaGetProp(ctxt, node, "version");
3976 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003977 if (val != NULL) {
3978 if (xmlStrEqual(val, BAD_CAST "qualified"))
3979 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3980 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3981 xmlSchemaPErr2(ctxt, node, child,
3982 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3983 "Invalid value %s for elementFormDefault\n",
3984 val, NULL);
3985 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003986 } else {
3987 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3988 }
3989 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003990 if (val != NULL) {
3991 if (xmlStrEqual(val, BAD_CAST "qualified"))
3992 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3993 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3994 xmlSchemaPErr2(ctxt, node, child,
3995 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3996 "Invalid value %s for attributeFormDefault\n",
3997 val, NULL);
3998 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003999 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004000
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004001 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
4002 } else {
4003 xmlDocPtr doc;
4004
4005 doc = node->doc;
4006
4007 if ((doc != NULL) && (doc->URL != NULL)) {
4008 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4009 XML_SCHEMAP_NOT_SCHEMA,
4010 "File %s is not a schemas", doc->URL, NULL);
4011 } else {
4012 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4013 XML_SCHEMAP_NOT_SCHEMA,
4014 "File is not a schemas", NULL, NULL);
4015 }
4016 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004017 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004018 if (ctxt->nberrors != 0) {
4019 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004020 xmlSchemaFree(schema);
4021 schema = NULL;
4022 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004023 }
4024 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004025#ifdef DEBUG
4026 if (schema == NULL)
4027 xmlGenericError(xmlGenericErrorContext,
4028 "xmlSchemaParse() failed\n");
4029#endif
4030
4031 return (schema);
4032}
4033
4034/************************************************************************
4035 * *
4036 * Validating using Schemas *
4037 * *
4038 ************************************************************************/
4039
4040/************************************************************************
4041 * *
4042 * Reading/Writing Schemas *
4043 * *
4044 ************************************************************************/
4045
4046/**
4047 * xmlSchemaNewParserCtxt:
4048 * @URL: the location of the schema
4049 *
4050 * Create an XML Schemas parse context for that file/resource expected
4051 * to contain an XML Schemas file.
4052 *
4053 * Returns the parser context or NULL in case of error
4054 */
4055xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004056xmlSchemaNewParserCtxt(const char *URL)
4057{
Daniel Veillard4255d502002-04-16 15:50:10 +00004058 xmlSchemaParserCtxtPtr ret;
4059
4060 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004061 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004062
4063 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4064 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004065 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4066 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004067 return (NULL);
4068 }
4069 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004070 ret->dict = xmlDictCreate();
4071 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004072 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004073 return (ret);
4074}
4075
4076/**
Daniel Veillard6045c902002-10-09 21:13:59 +00004077 * xmlSchemaNewMemParserCtxt:
4078 * @buffer: a pointer to a char array containing the schemas
4079 * @size: the size of the array
4080 *
4081 * Create an XML Schemas parse context for that memory buffer expected
4082 * to contain an XML Schemas file.
4083 *
4084 * Returns the parser context or NULL in case of error
4085 */
4086xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004087xmlSchemaNewMemParserCtxt(const char *buffer, int size)
4088{
Daniel Veillard6045c902002-10-09 21:13:59 +00004089 xmlSchemaParserCtxtPtr ret;
4090
4091 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004092 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00004093
4094 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4095 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004096 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4097 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00004098 return (NULL);
4099 }
4100 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4101 ret->buffer = buffer;
4102 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00004103 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00004104 return (ret);
4105}
4106
4107/**
Daniel Veillard9d751502003-10-29 13:21:47 +00004108 * xmlSchemaNewDocParserCtxt:
4109 * @doc: a preparsed document tree
4110 *
4111 * Create an XML Schemas parse context for that document.
4112 * NB. The document may be modified during the parsing process.
4113 *
4114 * Returns the parser context or NULL in case of error
4115 */
4116xmlSchemaParserCtxtPtr
4117xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
4118{
4119 xmlSchemaParserCtxtPtr ret;
4120
4121 if (doc == NULL)
4122 return (NULL);
4123
4124 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4125 if (ret == NULL) {
4126 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
4127 NULL);
4128 return (NULL);
4129 }
4130 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4131 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00004132 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00004133 /* The application has responsibility for the document */
4134 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00004135
4136 return (ret);
4137}
4138
4139/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004140 * xmlSchemaFreeParserCtxt:
4141 * @ctxt: the schema parser context
4142 *
4143 * Free the resources associated to the schema parser context
4144 */
4145void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004146xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
4147{
Daniel Veillard4255d502002-04-16 15:50:10 +00004148 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004149 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004150 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004151 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004152 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004153 xmlFree(ctxt);
4154}
4155
4156/************************************************************************
4157 * *
4158 * Building the content models *
4159 * *
4160 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004161
Daniel Veillard4255d502002-04-16 15:50:10 +00004162/**
4163 * xmlSchemaBuildAContentModel:
4164 * @type: the schema type definition
4165 * @ctxt: the schema parser context
4166 * @name: the element name whose content is being built
4167 *
4168 * Generate the automata sequence needed for that type
4169 */
4170static void
4171xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004172 xmlSchemaParserCtxtPtr ctxt,
4173 const xmlChar * name)
4174{
Daniel Veillard4255d502002-04-16 15:50:10 +00004175 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004176 xmlGenericError(xmlGenericErrorContext,
4177 "Found unexpected type = NULL in %s content model\n",
4178 name);
4179 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004180 }
4181 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004182 case XML_SCHEMA_TYPE_ANY:
4183 /* TODO : handle the namespace too */
4184 /* TODO : make that a specific transition type */
4185 TODO ctxt->state =
4186 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
4187 BAD_CAST "*", NULL);
4188 break;
4189 case XML_SCHEMA_TYPE_ELEMENT:{
4190 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00004191
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004192 /* TODO : handle the namespace too */
4193 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004194
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004195 if (elem->maxOccurs >= UNBOUNDED) {
4196 if (elem->minOccurs > 1) {
4197 xmlAutomataStatePtr tmp;
4198 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00004199
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004200 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4201 oldstate,
4202 NULL);
4203 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004204
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004205 counter = xmlAutomataNewCounter(ctxt->am,
4206 elem->minOccurs -
4207 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00004208
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004209 if (elem->refDecl != NULL) {
4210 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4211 elem->refDecl,
4212 ctxt,
4213 elem->refDecl->
4214 name);
4215 } else {
4216 ctxt->state =
4217 xmlAutomataNewTransition(ctxt->am,
4218 ctxt->state, NULL,
4219 elem->name, type);
4220 }
4221 tmp = ctxt->state;
4222 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4223 counter);
4224 ctxt->state =
4225 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4226 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00004227
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004228 } else {
4229 if (elem->refDecl != NULL) {
4230 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4231 elem->refDecl,
4232 ctxt,
4233 elem->refDecl->
4234 name);
4235 } else {
4236 ctxt->state =
4237 xmlAutomataNewTransition(ctxt->am,
4238 ctxt->state, NULL,
4239 elem->name, type);
4240 }
4241 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4242 oldstate);
4243 if (elem->minOccurs == 0) {
4244 /* basically an elem* */
4245 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4246 ctxt->state);
4247 }
4248 }
4249 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
4250 xmlAutomataStatePtr tmp;
4251 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00004252
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004253 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4254 oldstate, NULL);
4255 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004256
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004257 counter = xmlAutomataNewCounter(ctxt->am,
4258 elem->minOccurs - 1,
4259 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004260
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004261 if (elem->refDecl != NULL) {
4262 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4263 elem->refDecl, ctxt,
4264 elem->refDecl->name);
4265 } else {
4266 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4267 ctxt->state,
4268 NULL,
4269 elem->name,
4270 type);
4271 }
4272 tmp = ctxt->state;
4273 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4274 counter);
4275 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
4276 NULL,
4277 counter);
4278 if (elem->minOccurs == 0) {
4279 /* basically an elem? */
4280 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4281 ctxt->state);
4282 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00004283
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004284 } else {
4285 if (elem->refDecl != NULL) {
4286 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4287 elem->refDecl, ctxt,
4288 elem->refDecl->name);
4289 } else {
4290 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4291 ctxt->state,
4292 NULL,
4293 elem->name,
4294 type);
4295 }
4296 if (elem->minOccurs == 0) {
4297 /* basically an elem? */
4298 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4299 ctxt->state);
4300 }
4301 }
4302 break;
4303 }
4304 case XML_SCHEMA_TYPE_SEQUENCE:{
4305 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004306
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004307 /*
4308 * If max and min occurances are default (1) then
4309 * simply iterate over the subtypes
4310 */
4311 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4312 subtypes = type->subtypes;
4313 while (subtypes != NULL) {
4314 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4315 subtypes = subtypes->next;
4316 }
4317 } else {
4318 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004319
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004320 if (type->maxOccurs >= UNBOUNDED) {
4321 if (type->minOccurs > 1) {
4322 xmlAutomataStatePtr tmp;
4323 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004324
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004325 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4326 oldstate,
4327 NULL);
4328 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004329
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004330 counter = xmlAutomataNewCounter(ctxt->am,
4331 type->
4332 minOccurs - 1,
4333 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004334
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004335 subtypes = type->subtypes;
4336 while (subtypes != NULL) {
4337 xmlSchemaBuildAContentModel(subtypes, ctxt,
4338 name);
4339 subtypes = subtypes->next;
4340 }
4341 tmp = ctxt->state;
4342 xmlAutomataNewCountedTrans(ctxt->am, tmp,
4343 oldstate, counter);
4344 ctxt->state =
4345 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4346 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004347
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004348 } else {
4349 subtypes = type->subtypes;
4350 while (subtypes != NULL) {
4351 xmlSchemaBuildAContentModel(subtypes, ctxt,
4352 name);
4353 subtypes = subtypes->next;
4354 }
4355 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4356 oldstate);
4357 if (type->minOccurs == 0) {
4358 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4359 ctxt->state);
4360 }
4361 }
4362 } else if ((type->maxOccurs > 1)
4363 || (type->minOccurs > 1)) {
4364 xmlAutomataStatePtr tmp;
4365 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004366
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004367 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4368 oldstate,
4369 NULL);
4370 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00004371
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004372 counter = xmlAutomataNewCounter(ctxt->am,
4373 type->minOccurs -
4374 1,
4375 type->maxOccurs -
4376 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004377
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004378 subtypes = type->subtypes;
4379 while (subtypes != NULL) {
4380 xmlSchemaBuildAContentModel(subtypes, ctxt,
4381 name);
4382 subtypes = subtypes->next;
4383 }
4384 tmp = ctxt->state;
4385 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4386 counter);
4387 ctxt->state =
4388 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4389 counter);
4390 if (type->minOccurs == 0) {
4391 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4392 ctxt->state);
4393 }
Daniel Veillardb509f152002-04-17 16:28:10 +00004394
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004395 } else {
4396 subtypes = type->subtypes;
4397 while (subtypes != NULL) {
4398 xmlSchemaBuildAContentModel(subtypes, ctxt,
4399 name);
4400 subtypes = subtypes->next;
4401 }
4402 if (type->minOccurs == 0) {
4403 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4404 ctxt->state);
4405 }
4406 }
4407 }
4408 break;
4409 }
4410 case XML_SCHEMA_TYPE_CHOICE:{
4411 xmlSchemaTypePtr subtypes;
4412 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00004413
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414 start = ctxt->state;
4415 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00004416
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004417 /*
4418 * iterate over the subtypes and remerge the end with an
4419 * epsilon transition
4420 */
4421 if (type->maxOccurs == 1) {
4422 subtypes = type->subtypes;
4423 while (subtypes != NULL) {
4424 ctxt->state = start;
4425 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4426 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4427 subtypes = subtypes->next;
4428 }
4429 } else {
4430 int counter;
4431 xmlAutomataStatePtr hop;
4432 int maxOccurs = type->maxOccurs == UNBOUNDED ?
4433 UNBOUNDED : type->maxOccurs - 1;
4434 int minOccurs =
4435 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00004436
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004437 /*
4438 * use a counter to keep track of the number of transtions
4439 * which went through the choice.
4440 */
4441 counter =
4442 xmlAutomataNewCounter(ctxt->am, minOccurs,
4443 maxOccurs);
4444 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00004445
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004446 subtypes = type->subtypes;
4447 while (subtypes != NULL) {
4448 ctxt->state = start;
4449 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4450 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4451 subtypes = subtypes->next;
4452 }
4453 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4454 counter);
4455 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4456 counter);
4457 }
4458 if (type->minOccurs == 0) {
4459 xmlAutomataNewEpsilon(ctxt->am, start, end);
4460 }
4461 ctxt->state = end;
4462 break;
4463 }
4464 case XML_SCHEMA_TYPE_ALL:{
4465 xmlAutomataStatePtr start;
4466 xmlSchemaTypePtr subtypes;
4467 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4468 int lax;
4469
4470 subtypes = type->subtypes;
4471 if (subtypes == NULL)
4472 break;
4473 start = ctxt->state;
4474 while (subtypes != NULL) {
4475 ctxt->state = start;
William M. Bracke7091952004-05-11 15:09:58 +00004476 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004477 /* TODO : handle the namespace too */
4478 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4479 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4480 ctxt->state, elem->name, 1,
4481 1, subtypes);
4482 } else {
4483 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4484 ctxt->state, elem->name,
4485 elem->minOccurs,
4486 elem->maxOccurs,
4487 subtypes);
4488 }
4489 subtypes = subtypes->next;
4490 }
4491 lax = type->minOccurs == 0;
4492 ctxt->state =
4493 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4494 lax);
4495 break;
4496 }
4497 case XML_SCHEMA_TYPE_RESTRICTION:
4498 if (type->subtypes != NULL)
4499 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4500 break;
4501 case XML_SCHEMA_TYPE_EXTENSION:
4502 if (type->baseType != NULL) {
4503 xmlSchemaTypePtr subtypes;
4504
Daniel Veillardf7627552004-04-22 07:15:40 +00004505 if (type->recurse) {
4506 xmlSchemaPErr(ctxt, type->node,
4507 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4508 "Schemas: extension type %s is recursive\n",
4509 type->name, NULL);
4510 return;
4511 }
4512 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004513 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00004514 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004515 subtypes = type->subtypes;
4516 while (subtypes != NULL) {
4517 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4518 subtypes = subtypes->next;
4519 }
4520 } else if (type->subtypes != NULL)
4521 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4522 break;
4523 case XML_SCHEMA_TYPE_GROUP:
4524 if (type->subtypes == NULL) {
William M. Brack29aa7722004-05-12 00:27:56 +00004525 xmlSchemaTypePtr rgroup;
4526 if (type->ref != NULL) {
4527 rgroup = xmlHashLookup2(ctxt->schema->groupDecl, type->ref,
4528 type->refNs);
4529 if (rgroup == NULL) {
4530 xmlSchemaPErr(ctxt, type->node,
4531 XML_SCHEMAP_UNKNOWN_REF,
4532 "Schemas: group %s reference %s is not found",
4533 name, type->ref);
4534 return;
4535 }
4536 xmlSchemaBuildAContentModel(rgroup, ctxt, name);
4537 break;
4538 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004539 }
4540 case XML_SCHEMA_TYPE_COMPLEX:
4541 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4542 if (type->subtypes != NULL)
4543 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4544 break;
4545 default:
4546 xmlGenericError(xmlGenericErrorContext,
4547 "Found unexpected type %d in %s content model\n",
4548 type->type, name);
4549 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004550 }
4551}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004552
Daniel Veillard4255d502002-04-16 15:50:10 +00004553/**
4554 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004555 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00004556 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004557 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00004558 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004559 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00004560 */
4561static void
4562xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004563 xmlSchemaParserCtxtPtr ctxt,
4564 const xmlChar * name)
4565{
Daniel Veillard4255d502002-04-16 15:50:10 +00004566 xmlAutomataStatePtr start;
4567
Daniel Veillard4255d502002-04-16 15:50:10 +00004568 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004569 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004570 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004571 elem->contentType = XML_SCHEMA_CONTENT_ANY;
4572 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004573 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004574 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004575 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004576 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
4577 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004578 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004579
4580#ifdef DEBUG_CONTENT
4581 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004582 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004583#endif
4584
Daniel Veillard4255d502002-04-16 15:50:10 +00004585 ctxt->am = xmlNewAutomata();
4586 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004587 xmlGenericError(xmlGenericErrorContext,
4588 "Cannot create automata for elem %s\n", name);
4589 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004590 }
4591 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
4592 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
4593 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00004594 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004595 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004596 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
4597 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004598 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004599 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
4600 "Content model of %s is not determinist:\n", name,
4601 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00004602 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00004603#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004604 xmlGenericError(xmlGenericErrorContext,
4605 "Content model of %s:\n", name);
4606 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004607#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00004608 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004609 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004610 xmlFreeAutomata(ctxt->am);
4611 ctxt->am = NULL;
4612}
4613
4614/**
4615 * xmlSchemaRefFixupCallback:
4616 * @elem: the schema element context
4617 * @ctxt: the schema parser context
4618 *
4619 * Free the resources associated to the schema parser context
4620 */
4621static void
4622xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004623 xmlSchemaParserCtxtPtr ctxt,
4624 const xmlChar * name,
4625 const xmlChar * context ATTRIBUTE_UNUSED,
4626 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004627{
4628 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004629 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004630 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004631 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004632
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004633 if (elem->subtypes != NULL) {
4634 xmlSchemaPErr(ctxt, elem->node,
4635 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
4636 "Schemas: element %s have both ref and subtype\n",
4637 name, NULL);
4638 return;
4639 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004640 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004641
4642 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004643 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
4644 "Schemas: element %s ref to %s not found\n",
4645 name, elem->ref);
4646 return;
4647 }
4648 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004649 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004650 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004651
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004652 if (elem->subtypes != NULL) {
4653 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
4654 "Schemas: element %s have both type and subtype\n",
4655 name, NULL);
4656 return;
4657 }
4658 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
4659 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00004660
4661 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004662 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
4663 "Schemas: element %s type %s not found\n", name,
4664 elem->namedType);
4665 return;
4666 }
4667 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004668 }
4669}
4670
William M. Bracke7091952004-05-11 15:09:58 +00004671/**
4672 * xmlSchemaParseListRefFixup:
4673 * @type: the schema type definition
4674 * @ctxt: the schema parser context
4675 *
4676 * Fixup of the itemType reference of the list type.
4677 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00004678static void
William M. Bracke7091952004-05-11 15:09:58 +00004679xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
4680{
4681 const xmlChar *itemType, *namespace;
4682 xmlSchemaTypePtr subtype;
4683
4684 /* Handle the "itemType" attribute. */
William M. Brack29aa7722004-05-12 00:27:56 +00004685 itemType = xmlGetQNameProp(ctxt, type->node, "itemType", &namespace);
William M. Bracke7091952004-05-11 15:09:58 +00004686 if (itemType != NULL) {
4687 /* Do not allow more that one item type. */
4688 if (type->subtypes != NULL) {
4689 xmlSchemaPErr(ctxt, type->node,
4690 XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE,
4691 "List %s has more than one item type defined\n",
4692 type->name, NULL);
4693 }
4694 subtype = xmlSchemaGetType(ctxt->schema, itemType, namespace);
4695 if (subtype == NULL) {
4696 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_TYPE,
4697 "List %s references an unknown item type: %s\n",
4698 type->name, xmlSchemaGetProp(ctxt, type->node,
William M. Brack29aa7722004-05-12 00:27:56 +00004699 "itemType"));
William M. Bracke7091952004-05-11 15:09:58 +00004700 } else
4701 type->subtypes = subtype;
4702 }
4703}
4704
4705/**
4706 * xmlSchemaParseUnionRefCheck:
4707 * @typeDecl: the schema type definition
4708 * @ctxt: the schema parser context
4709 *
4710 * Checks the memberTypes references of the union type.
4711 */
4712static void
4713xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00004714 xmlSchemaParserCtxtPtr ctxt)
4715{
4716 const xmlChar *cur, *end, *prefix, *ncName, *namespace;
4717 xmlChar *tmp;
4718 xmlSchemaTypePtr subtype;
4719 xmlNsPtr ns;
4720 int len;
4721
William M. Bracke7091952004-05-11 15:09:58 +00004722 if ((type->type != XML_SCHEMA_TYPE_UNION) || (type->ref == NULL))
Daniel Veillard377e1a92004-04-16 16:30:05 +00004723 return;
4724
William M. Bracke7091952004-05-11 15:09:58 +00004725 cur = type->ref;
Daniel Veillard377e1a92004-04-16 16:30:05 +00004726 do {
4727 while (IS_BLANK_CH(*cur))
4728 cur++;
4729 end = cur;
4730 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4731 end++;
4732 if (end == cur)
4733 break;
4734 tmp = xmlStrndup(cur, end - cur);
4735 ncName = xmlSplitQName3(tmp, &len);
4736 if (ncName != NULL) {
4737 prefix = xmlDictLookup(ctxt->dict, tmp, len);
4738 } else {
4739 prefix = NULL;
4740 ncName = tmp;
4741 }
William M. Bracke7091952004-05-11 15:09:58 +00004742 ns = xmlSearchNs(type->node->doc, type->node, prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004743 if (ns == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00004744 if (prefix != NULL) {
4745 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_PREFIX_UNDEFINED,
4746 "Union %s: the namespace prefix of member type "
4747 "%s is undefined\n",
4748 type->name, (const xmlChar *) tmp);
4749 }
4750 namespace = NULL;
Daniel Veillard377e1a92004-04-16 16:30:05 +00004751 } else {
4752 namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4753 }
4754 /* Lookup the referenced type */
4755 subtype = xmlSchemaGetType(ctxt->schema, ncName, namespace);
4756 if (subtype == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00004757 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
4758 "Union %s references an unknown member type %s\n",
4759 type->name, (const xmlChar *) tmp);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004760 }
William M. Bracke7091952004-05-11 15:09:58 +00004761 xmlFree(tmp);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004762 cur = end;
William M. Bracke7091952004-05-11 15:09:58 +00004763 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004764}
4765
Daniel Veillard4255d502002-04-16 15:50:10 +00004766/**
4767 * xmlSchemaTypeFixup:
4768 * @typeDecl: the schema type definition
4769 * @ctxt: the schema parser context
4770 *
4771 * Fixes the content model of the type.
4772 */
4773static void
4774xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004775 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004776{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00004777 if (typeDecl == NULL)
4778 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004779 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004780 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004781 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004782 switch (typeDecl->type) {
4783 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4784 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4785 if (typeDecl->subtypes != NULL)
4786 typeDecl->contentType =
4787 typeDecl->subtypes->contentType;
4788 break;
4789 }
4790 case XML_SCHEMA_TYPE_RESTRICTION:{
4791 if (typeDecl->subtypes != NULL)
4792 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004793
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004794 if (typeDecl->base != NULL) {
4795 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004796
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004797 baseType =
4798 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4799 typeDecl->baseNs);
4800 if (baseType == NULL) {
4801 xmlSchemaPErr(ctxt, typeDecl->node,
4802 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004803 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004804 name, typeDecl->base);
4805 }
4806 typeDecl->baseType = baseType;
4807 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004808 if (typeDecl->subtypes == NULL)
William M. Bracke7091952004-05-11 15:09:58 +00004809 if (typeDecl->baseType != NULL) {
4810 /* The base type might be not "type fixed" yet,
4811 * so do it now. */
4812 if (typeDecl->baseType->contentType ==
4813 XML_SCHEMA_CONTENT_UNKNOWN)
4814 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004815 typeDecl->contentType =
4816 typeDecl->baseType->contentType;
William M. Bracke7091952004-05-11 15:09:58 +00004817 } else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004818 /* 1.1.1 */
4819 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004820 else if ((typeDecl->subtypes->subtypes == NULL) &&
4821 ((typeDecl->subtypes->type ==
4822 XML_SCHEMA_TYPE_ALL)
4823 || (typeDecl->subtypes->type ==
4824 XML_SCHEMA_TYPE_SEQUENCE)))
4825 /* 1.1.2 */
4826 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4827 else if ((typeDecl->subtypes->type ==
4828 XML_SCHEMA_TYPE_CHOICE)
4829 && (typeDecl->subtypes->subtypes == NULL))
4830 /* 1.1.3 */
4831 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4832 else {
4833 /* 1.2 and 2.X are applied at the other layer */
4834 typeDecl->contentType =
4835 XML_SCHEMA_CONTENT_ELEMENTS;
4836 }
4837 break;
4838 }
4839 case XML_SCHEMA_TYPE_EXTENSION:{
4840 xmlSchemaContentType explicitContentType;
4841 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004842
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004843 if (typeDecl->base != NULL) {
4844 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004845
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004846 baseType =
4847 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4848 typeDecl->baseNs);
4849 if (baseType == NULL) {
4850 xmlSchemaPErr(ctxt, typeDecl->node,
4851 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004852 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004853 name, typeDecl->base);
4854 }
4855 typeDecl->baseType = baseType;
4856 }
4857 if (typeDecl->subtypes != NULL)
4858 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004859
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004860 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4861 if (typeDecl->subtypes == NULL)
4862 /* 1.1.1 */
4863 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4864 else if ((typeDecl->subtypes->subtypes == NULL) &&
4865 ((typeDecl->subtypes->type ==
4866 XML_SCHEMA_TYPE_ALL)
4867 || (typeDecl->subtypes->type ==
4868 XML_SCHEMA_TYPE_SEQUENCE)))
4869 /* 1.1.2 */
4870 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4871 else if ((typeDecl->subtypes->type ==
4872 XML_SCHEMA_TYPE_CHOICE)
4873 && (typeDecl->subtypes->subtypes == NULL))
4874 /* 1.1.3 */
4875 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004876
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004877 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4878 typeDecl->baseNs);
4879 if (base == NULL) {
4880 xmlSchemaPErr(ctxt, typeDecl->node,
4881 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4882 "Schemas: base type %s of type %s not found\n",
4883 typeDecl->base, name);
4884 return;
4885 }
Daniel Veillard2582a332004-04-18 19:49:46 +00004886 if (typeDecl->recurse) {
4887 xmlSchemaPErr(ctxt, typeDecl->node,
4888 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4889 "Schemas: extension type %s is recursive\n",
4890 name, NULL);
4891 return;
4892 }
4893 typeDecl->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004894 xmlSchemaTypeFixup(base, ctxt, NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +00004895 typeDecl->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004896 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4897 /* 2.1 */
4898 typeDecl->contentType = base->contentType;
4899 } else if (base->contentType ==
4900 XML_SCHEMA_CONTENT_EMPTY) {
4901 /* 2.2 imbitable ! */
4902 typeDecl->contentType =
4903 XML_SCHEMA_CONTENT_ELEMENTS;
4904 } else {
4905 /* 2.3 imbitable pareil ! */
4906 typeDecl->contentType =
4907 XML_SCHEMA_CONTENT_ELEMENTS;
4908 }
4909 break;
4910 }
4911 case XML_SCHEMA_TYPE_COMPLEX:{
4912 if (typeDecl->subtypes == NULL) {
4913 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004914
4915 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4916 typeDecl->contentType =
4917 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004918 } else {
4919 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4920 typeDecl->contentType =
4921 XML_SCHEMA_CONTENT_MIXED;
4922 else {
4923 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4924 NULL);
4925 if (typeDecl->subtypes != NULL)
4926 typeDecl->contentType =
4927 typeDecl->subtypes->contentType;
4928 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004929 if (typeDecl->attributes == NULL)
4930 typeDecl->attributes =
4931 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004932 }
4933 break;
4934 }
4935 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4936 if (typeDecl->subtypes == NULL) {
4937 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004938 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4939 typeDecl->contentType =
4940 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004941 } else {
4942 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4943 typeDecl->contentType =
4944 XML_SCHEMA_CONTENT_MIXED;
4945 else {
4946 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4947 NULL);
4948 if (typeDecl->subtypes != NULL)
4949 typeDecl->contentType =
4950 typeDecl->subtypes->contentType;
4951 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004952 if (typeDecl->attributes == NULL)
4953 typeDecl->attributes =
4954 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004955 }
4956 break;
4957 }
4958 case XML_SCHEMA_TYPE_SEQUENCE:
4959 case XML_SCHEMA_TYPE_GROUP:
4960 case XML_SCHEMA_TYPE_ALL:
4961 case XML_SCHEMA_TYPE_CHOICE:
4962 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4963 break;
4964 case XML_SCHEMA_TYPE_BASIC:
4965 case XML_SCHEMA_TYPE_ANY:
4966 case XML_SCHEMA_TYPE_FACET:
4967 case XML_SCHEMA_TYPE_SIMPLE:
4968 case XML_SCHEMA_TYPE_UR:
4969 case XML_SCHEMA_TYPE_ELEMENT:
4970 case XML_SCHEMA_TYPE_ATTRIBUTE:
4971 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +00004972 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004973 case XML_SCHEMA_TYPE_NOTATION:
4974 case XML_SCHEMA_TYPE_LIST:
William M. Bracke7091952004-05-11 15:09:58 +00004975 xmlSchemaParseListRefFixup(typeDecl, ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004976 case XML_SCHEMA_TYPE_UNION:
Daniel Veillard377e1a92004-04-16 16:30:05 +00004977 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004978 case XML_SCHEMA_FACET_MININCLUSIVE:
4979 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4980 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4981 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4982 case XML_SCHEMA_FACET_TOTALDIGITS:
4983 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4984 case XML_SCHEMA_FACET_PATTERN:
4985 case XML_SCHEMA_FACET_ENUMERATION:
4986 case XML_SCHEMA_FACET_WHITESPACE:
4987 case XML_SCHEMA_FACET_LENGTH:
4988 case XML_SCHEMA_FACET_MAXLENGTH:
4989 case XML_SCHEMA_FACET_MINLENGTH:
4990 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004991 if (typeDecl->subtypes != NULL)
4992 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004993 break;
4994 }
4995 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004996#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004997 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004998 xmlGenericError(xmlGenericErrorContext,
4999 "Type of %s : %s:%d :", name,
5000 typeDecl->node->doc->URL,
5001 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005002 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005003 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005004 }
Daniel Veillard8651f532002-04-17 09:06:27 +00005005 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005006 case XML_SCHEMA_CONTENT_SIMPLE:
5007 xmlGenericError(xmlGenericErrorContext, "simple\n");
5008 break;
5009 case XML_SCHEMA_CONTENT_ELEMENTS:
5010 xmlGenericError(xmlGenericErrorContext, "elements\n");
5011 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005012 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005013 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
5014 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005015 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005016 xmlGenericError(xmlGenericErrorContext, "empty\n");
5017 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005018 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005019 xmlGenericError(xmlGenericErrorContext, "mixed\n");
5020 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005021 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005022 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
5023 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005024 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005025 xmlGenericError(xmlGenericErrorContext, "basic\n");
5026 break;
5027 default:
5028 xmlGenericError(xmlGenericErrorContext,
5029 "not registered !!!\n");
5030 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00005031 }
5032#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00005033}
5034
5035/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005036 * xmlSchemaCheckFacet:
5037 * @facet: the facet
5038 * @typeDecl: the schema type definition
5039 * @ctxt: the schema parser context or NULL
5040 * @name: name of the type
5041 *
5042 * Checks the default values types, especially for facets
5043 *
5044 * Returns 0 if okay or -1 in cae of error
5045 */
5046int
5047xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005048 xmlSchemaTypePtr typeDecl,
5049 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005050{
5051 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
5052 int ret = 0;
5053
5054 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005055 nonNegativeIntegerType =
5056 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
5057 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005058 }
5059 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005060 case XML_SCHEMA_FACET_MININCLUSIVE:
5061 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5062 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5063 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
5064 /*
5065 * Okay we need to validate the value
5066 * at that point.
5067 */
5068 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005069
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005070 vctxt = xmlSchemaNewValidCtxt(NULL);
5071 if (vctxt == NULL)
5072 break;
5073 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
5074 facet->value);
5075 facet->val = vctxt->value;
5076 vctxt->value = NULL;
5077 if (facet->val == NULL) {
5078 /* error code */
5079 if (ctxt != NULL) {
5080 xmlSchemaPErr(ctxt, facet->node,
5081 XML_SCHEMAP_INVALID_FACET,
5082 "Schemas: type %s facet value %s invalid\n",
5083 name, facet->value);
5084 }
5085 ret = -1;
5086 }
5087 xmlSchemaFreeValidCtxt(vctxt);
5088 break;
5089 }
5090 case XML_SCHEMA_FACET_ENUMERATION:{
5091 /*
5092 * Okay we need to validate the value
5093 * at that point.
5094 */
5095 xmlSchemaValidCtxtPtr vctxt;
5096 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005097
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005098 vctxt = xmlSchemaNewValidCtxt(NULL);
5099 if (vctxt == NULL)
5100 break;
5101 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
5102 facet->value);
5103 if (tmp != 0) {
5104 if (ctxt != NULL) {
5105 xmlSchemaPErr(ctxt, facet->node,
5106 XML_SCHEMAP_INVALID_ENUM,
5107 "Schemas: type %s enumeration value %s invalid\n",
5108 name, facet->value);
5109 }
5110 ret = -1;
5111 }
5112 xmlSchemaFreeValidCtxt(vctxt);
5113 break;
5114 }
5115 case XML_SCHEMA_FACET_PATTERN:
5116 facet->regexp = xmlRegexpCompile(facet->value);
5117 if (facet->regexp == NULL) {
5118 xmlSchemaPErr(ctxt, typeDecl->node,
5119 XML_SCHEMAP_REGEXP_INVALID,
5120 "Schemas: type %s facet regexp %s invalid\n",
5121 name, facet->value);
5122 ret = -1;
5123 }
5124 break;
5125 case XML_SCHEMA_FACET_TOTALDIGITS:
5126 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5127 case XML_SCHEMA_FACET_LENGTH:
5128 case XML_SCHEMA_FACET_MAXLENGTH:
5129 case XML_SCHEMA_FACET_MINLENGTH:{
5130 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005131
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005132 tmp =
5133 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
5134 facet->value,
5135 &facet->val);
5136 if (tmp != 0) {
5137 /* error code */
5138 if (ctxt != NULL) {
5139 xmlSchemaPErr(ctxt, facet->node,
5140 XML_SCHEMAP_INVALID_FACET_VALUE,
5141 "Schemas: type %s facet value %s invalid\n",
5142 name, facet->value);
5143 }
5144 ret = -1;
5145 }
5146 break;
5147 }
5148 case XML_SCHEMA_FACET_WHITESPACE:{
5149 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
5150 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
5151 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
5152 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
5153 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
5154 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
5155 } else {
5156 if (ctxt != NULL) {
5157 xmlSchemaPErr(ctxt, facet->node,
5158 XML_SCHEMAP_INVALID_WHITE_SPACE,
5159 "Schemas: type %s whiteSpace value %s invalid\n",
5160 name, facet->value);
5161 }
5162 ret = -1;
5163 }
5164 }
5165 default:
5166 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005167 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005168 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005169}
5170
5171/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005172 * xmlSchemaCheckDefaults:
5173 * @typeDecl: the schema type definition
5174 * @ctxt: the schema parser context
5175 *
5176 * Checks the default values types, especially for facets
5177 */
5178static void
5179xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005180 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00005181{
Daniel Veillard4255d502002-04-16 15:50:10 +00005182 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005183 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005184 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005185 if (typeDecl->facets != NULL) {
5186 xmlSchemaFacetPtr facet = typeDecl->facets;
5187
5188 while (facet != NULL) {
5189 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
5190 facet = facet->next;
5191 }
5192 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005193 }
5194}
5195
5196/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00005197 * xmlSchemaAttrGrpFixup:
5198 * @attrgrpDecl: the schema attribute definition
5199 * @ctxt: the schema parser context
5200 * @name: the attribute name
5201 *
5202 * Fixes finish doing the computations on the attributes definitions
5203 */
5204static void
5205xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005206 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00005207{
5208 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005209 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005210 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005211 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005212 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005213 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005214
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005215 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
5216 attrgrpDecl->refNs);
5217 if (ref == NULL) {
5218 xmlSchemaPErr(ctxt, attrgrpDecl->node,
5219 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
5220 "Schemas: attribute group %s reference %s not found\n",
5221 name, attrgrpDecl->ref);
5222 return;
5223 }
5224 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
5225 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00005226 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005227 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
5228 "Schemas: attribute %s has no attributes nor reference\n",
5229 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00005230 }
5231}
5232
5233/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005234 * xmlSchemaAttrFixup:
5235 * @attrDecl: the schema attribute definition
5236 * @ctxt: the schema parser context
5237 * @name: the attribute name
5238 *
5239 * Fixes finish doing the computations on the attributes definitions
5240 */
5241static void
5242xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005243 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00005244{
5245 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005246 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005247 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005248 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005249 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005250 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005251
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005252 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
5253 attrDecl->typeNs);
5254 if (type == NULL) {
5255 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
5256 "Schemas: attribute %s type %s not found\n",
5257 name, attrDecl->typeName);
5258 }
5259 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005260 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005261 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00005262
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005263 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
5264 attrDecl->refNs);
5265 if (ref == NULL) {
5266 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
5267 "Schemas: attribute %s reference %s not found\n",
5268 name, attrDecl->ref);
5269 return;
5270 }
5271 xmlSchemaAttrFixup(ref, ctxt, NULL);
5272 attrDecl->subtypes = ref->subtypes;
William M. Bracke7091952004-05-11 15:09:58 +00005273 } else if (attrDecl->type != XML_SCHEMA_TYPE_ANY_ATTRIBUTE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005274 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
5275 "Schemas: attribute %s has no type nor reference\n",
5276 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005277 }
5278}
5279
5280/**
5281 * xmlSchemaParse:
5282 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00005283 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00005284 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00005285 * XML Shema struture which can be used to validate instances.
5286 * *WARNING* this interface is highly subject to change
5287 *
5288 * Returns the internal XML Schema structure built from the resource or
5289 * NULL in case of error
5290 */
5291xmlSchemaPtr
5292xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
5293{
5294 xmlSchemaPtr ret = NULL;
5295 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005296 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005297 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005298 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005299
5300 xmlSchemaInitTypes();
5301
Daniel Veillard6045c902002-10-09 21:13:59 +00005302 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00005303 return (NULL);
5304
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005305 nberrors = ctxt->nberrors;
5306 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005307 ctxt->counter = 0;
5308 ctxt->container = NULL;
5309
5310 /*
5311 * First step is to parse the input document into an DOM/Infoset
5312 */
Daniel Veillard6045c902002-10-09 21:13:59 +00005313 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005314 doc = xmlReadFile((const char *) ctxt->URL, NULL,
5315 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005316 if (doc == NULL) {
5317 xmlSchemaPErr(ctxt, NULL,
5318 XML_SCHEMAP_FAILED_LOAD,
5319 "xmlSchemaParse: could not load %s\n",
5320 ctxt->URL, NULL);
5321 return (NULL);
5322 }
Daniel Veillard6045c902002-10-09 21:13:59 +00005323 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005324 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
5325 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005326 if (doc == NULL) {
5327 xmlSchemaPErr(ctxt, NULL,
5328 XML_SCHEMAP_FAILED_PARSE,
5329 "xmlSchemaParse: could not parse\n",
5330 NULL, NULL);
5331 return (NULL);
5332 }
5333 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00005334 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00005335 } else if (ctxt->doc != NULL) {
5336 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005337 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00005338 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005339 xmlSchemaPErr(ctxt, NULL,
5340 XML_SCHEMAP_NOTHING_TO_PARSE,
5341 "xmlSchemaParse: could not parse\n",
5342 NULL, NULL);
5343 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005344 }
5345
5346 /*
5347 * Then extract the root and Schema parse it
5348 */
5349 root = xmlDocGetRootElement(doc);
5350 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005351 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
5352 XML_SCHEMAP_NOROOT,
5353 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00005354 if (!preserve) {
5355 xmlFreeDoc(doc);
5356 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005357 return (NULL);
5358 }
5359
5360 /*
5361 * Remove all the blank text nodes
5362 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005363 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00005364
5365 /*
5366 * Then do the parsing for good
5367 */
5368 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00005369 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00005370 if (!preserve) {
5371 xmlFreeDoc(doc);
5372 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005373 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00005374 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005375 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005376 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00005377
5378 /*
5379 * Then fix all the references.
5380 */
5381 ctxt->schema = ret;
5382 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005383 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005384
5385 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005386 * Then fixup all attributes declarations
5387 */
5388 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
5389
5390 /*
5391 * Then fixup all attributes group declarations
5392 */
5393 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
5394 ctxt);
5395
5396 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00005397 * Then fixup all types properties
5398 */
5399 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
5400
5401 /*
5402 * Then build the content model for all elements
5403 */
5404 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005405 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005406
5407 /*
5408 * Then check the defaults part of the type like facets values
5409 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005410 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
5411 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005412
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005413 if (ctxt->nberrors != 0) {
5414 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005415 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005416 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005417 return (ret);
5418}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005419
Daniel Veillard4255d502002-04-16 15:50:10 +00005420/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00005421 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00005422 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00005423 * @err: the error callback
5424 * @warn: the warning callback
5425 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00005426 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00005427 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00005428 */
5429void
5430xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005431 xmlSchemaValidityErrorFunc err,
5432 xmlSchemaValidityWarningFunc warn, void *ctx)
5433{
Daniel Veillard4255d502002-04-16 15:50:10 +00005434 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005435 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005436 ctxt->error = err;
5437 ctxt->warning = warn;
5438 ctxt->userData = ctx;
5439}
5440
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005441/**
5442 * xmlSchemaFacetTypeToString:
5443 * @type: the facet type
5444 *
5445 * Convert the xmlSchemaTypeType to a char string.
5446 *
5447 * Returns the char string representation of the facet type if the
5448 * type is a facet and an "Internal Error" string otherwise.
5449 */
5450static const char *
5451xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5452{
5453 switch (type) {
5454 case XML_SCHEMA_FACET_PATTERN:
5455 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005456 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005457 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005458 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005459 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005460 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005461 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005462 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005463 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005464 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005465 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005466 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005467 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005468 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005469 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005470 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005471 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005472 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005473 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005474 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005475 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005476 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005477 return ("fractionDigits");
5478 default:
5479 break;
5480 }
5481 return ("Internal Error");
5482}
5483
5484/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00005485 * xmlSchemaValidateFacetsInternal:
5486 * @ctxt: a schema validation context
5487 * @base: the base type
5488 * @facets: the list of facets to check
5489 * @value: the lexical repr of the value to validate
5490 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +00005491 * @fireErrors: if 0, only internal errors will be fired;
5492 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00005493 *
5494 * Check a value against all facet conditions
5495 *
5496 * Returns 0 if the element is schemas valid, a positive error code
5497 * number otherwise and -1 in case of internal or API error.
5498 */
5499static int
5500xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
5501 xmlSchemaTypePtr base,
William M. Bracke7091952004-05-11 15:09:58 +00005502 xmlSchemaFacetPtr facets,
5503 const xmlChar * value, int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00005504{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005505 int ret = 0;
5506 int tmp = 0;
5507 xmlSchemaTypeType type;
5508 xmlSchemaFacetPtr facet = facets;
5509
5510 while (facet != NULL) {
5511 type = facet->type;
5512 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005513 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005514
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005515 while (facet != NULL) {
5516 tmp =
5517 xmlSchemaValidateFacet(base, facet, value,
5518 ctxt->value);
5519 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005520 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005521 }
5522 facet = facet->next;
5523 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005524 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005525 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005526
5527 if (tmp != 0) {
5528 ret = tmp;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005529 if (fireErrors)
William M. Bracke7091952004-05-11 15:09:58 +00005530 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET,
5531 "Failed to validate type with facet %s\n",
5532 (const xmlChar *) xmlSchemaFacetTypeToString(type),
5533 NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005534 }
5535 if (facet != NULL)
5536 facet = facet->next;
5537 }
5538 return (ret);
5539}
5540
William M. Brack87640d52004-04-17 14:58:15 +00005541/**
5542 * xmlSchemaValidateFacets:
5543 * @ctxt: a schema validation context
5544 * @base: the base type
5545 * @facets: the list of facets to check
5546 * @value: the lexical repr of the value to validate
5547 * @val: the precomputed value
5548 *
5549 * Check a value against all facet conditions
5550 *
5551 * Returns 0 if the element is schemas valid, a positive error code
5552 * number otherwise and -1 in case of internal or API error.
5553 */
5554static int
5555xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5556 xmlSchemaTypePtr base,
5557 xmlSchemaFacetPtr facets, const xmlChar * value)
5558{
5559 return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
5560}
5561
Daniel Veillard4255d502002-04-16 15:50:10 +00005562/************************************************************************
5563 * *
5564 * Simple type validation *
5565 * *
5566 ************************************************************************/
5567
5568/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00005569 * xmlSchemaValidateSimpleValueUnion:
5570 * @ctxt: a schema validation context
5571 * @type: the type declaration
5572 * @value: the value to validate
5573 *
5574 * Validates a value against a union.
5575 *
5576 * Returns 0 if the value is valid, a positive error code
5577 * number otherwise and -1 in case of internal or API error.
5578 */
5579static int
5580xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
5581 xmlSchemaTypePtr type, const xmlChar * value)
5582{
5583 int ret = 0;
5584 const xmlChar *cur, *end, *prefix, *ncName;
5585 xmlChar *tmp;
5586 xmlSchemaTypePtr subtype;
5587 xmlNsPtr ns;
5588 int len;
5589
5590
5591 /* Process referenced memberTypes. */
5592 cur = type->ref;
5593 do {
5594 while (IS_BLANK_CH(*cur))
5595 cur++;
5596 end = cur;
5597 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5598 end++;
5599 if (end == cur)
5600 break;
5601 tmp = xmlStrndup(cur, end - cur);
5602 ncName = xmlSplitQName3(tmp, &len);
5603 if (ncName != NULL) {
5604 prefix = xmlStrndup(tmp, len);
5605 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
5606 } else {
5607 prefix = NULL;
5608 ncName = tmp;
5609 }
William M. Bracke7091952004-05-11 15:09:58 +00005610 /* We won't do additional checks here,
5611 * since they have been performed during parsing. */
Daniel Veillard377e1a92004-04-16 16:30:05 +00005612 ns = xmlSearchNs(type->node->doc, type->node, prefix);
5613 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
5614 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
5615 if (tmp != NULL)
5616 xmlFree(tmp);
5617 if (prefix != NULL)
William M. Brack87640d52004-04-17 14:58:15 +00005618 xmlFree((void *)prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005619 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5620 if ((ret == 0) || (ret == -1)) {
5621 return (ret);
5622 }
5623 cur = end;
5624 } while (*cur != 0);
5625
5626 if (type->subtypes != NULL) {
5627 subtype = type->subtypes;
5628 do {
5629 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5630 if ((ret == 0) || (ret == -1)) {
5631 return (ret);
5632 }
5633 subtype = subtype->next;
5634 } while (subtype != NULL);
5635 }
5636 return (ret);
5637}
5638
5639/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005640 * xmlSchemaValidateSimpleValue:
5641 * @ctxt: a schema validation context
5642 * @type: the type declaration
5643 * @value: the value to validate
5644 *
5645 * Validate a value against a simple type
5646 *
5647 * Returns 0 if the value is valid, a positive error code
5648 * number otherwise and -1 in case of internal or API error.
5649 */
5650static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005651xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005652 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005653{
Daniel Veillard377e1a92004-04-16 16:30:05 +00005654 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
5655}
5656
5657/**
5658 * xmlSchemaValidateSimpleValue:
5659 * @ctxt: a schema validation context
5660 * @type: the type declaration
5661 * @value: the value to validate
William M. Bracke7091952004-05-11 15:09:58 +00005662 * @fireErrors: if 0, only internal errors will be fired;
5663 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00005664 *
5665 * Validate a value against a simple type
5666 *
5667 * Returns 0 if the value is valid, a positive error code
5668 * number otherwise and -1 in case of internal or API error.
5669 */
5670static int
5671xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
William M. Bracke7091952004-05-11 15:09:58 +00005672 xmlSchemaTypePtr type,
5673 const xmlChar * value,
5674 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00005675{
Daniel Veillard4255d502002-04-16 15:50:10 +00005676 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005677
Daniel Veillard4255d502002-04-16 15:50:10 +00005678 /*
5679 * First normalize the value accordingly to Schema Datatype
5680 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
William M. Bracke7091952004-05-11 15:09:58 +00005681 *
Daniel Veillard4255d502002-04-16 15:50:10 +00005682 * Then check the normalized value against the lexical space of the
5683 * type.
5684 */
5685 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005686 if (ctxt->value != NULL) {
5687 xmlSchemaFreeValue(ctxt->value);
5688 ctxt->value = NULL;
5689 }
5690 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5691 ctxt->cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005692 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00005693 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
5694 "Failed to validate basic type %s\n",
5695 type->name, NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005696 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005697 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005698 xmlSchemaTypePtr base;
5699 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005700
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005701 base = type->baseType;
5702 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005703 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5704 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005705 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005706 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005707 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005708
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005709 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005710 * Do not validate facets or attributes when working on
5711 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005712 */
5713 if (ctxt->schema != NULL) {
5714 if (ret == 0) {
5715 facet = type->facets;
William M. Bracke7091952004-05-11 15:09:58 +00005716 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet,
5717 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005718 }
5719 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005720 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005721 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00005722
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005723 base = type->subtypes;
5724 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005725 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5726 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005727 } else {
5728 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00005729 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005730 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005731 const xmlChar *cur, *end;
5732 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005733 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00005734
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005735 base = type->subtypes;
5736 if (base == NULL) {
5737 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5738 "Internal: List type %s has no base type\n",
5739 type->name, NULL);
5740 return (-1);
5741 }
5742 cur = value;
5743 do {
William M. Brack76e95df2003-10-18 16:20:14 +00005744 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005745 cur++;
5746 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00005747 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005748 end++;
5749 if (end == cur)
5750 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005751 tmp = xmlStrndup(cur, end - cur);
William M. Bracke7091952004-05-11 15:09:58 +00005752 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base,
5753 tmp, fireErrors);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005754 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005755 if (ret2 != 0)
5756 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005757 cur = end;
5758 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005759 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
5760 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
5761 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00005762 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
5763 "Failed to validate type %s\n", type->name, NULL);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005764 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005765 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005766 TODO
5767 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005768 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005769}
5770
5771/************************************************************************
5772 * *
5773 * DOM Validation code *
5774 * *
5775 ************************************************************************/
5776
5777static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005778 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005779static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005780 xmlNodePtr elem,
5781 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005782static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005783 xmlNodePtr elem,
5784 xmlSchemaElementPtr elemDecl,
5785 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00005786
5787/**
5788 * xmlSchemaRegisterAttributes:
5789 * @ctxt: a schema validation context
5790 * @attrs: a list of attributes
5791 *
5792 * Register the list of attributes as the set to be validated on that element
5793 *
5794 * Returns -1 in case of error, 0 otherwise
5795 */
5796static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005797xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5798{
Daniel Veillard4255d502002-04-16 15:50:10 +00005799 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005800 if ((attrs->ns != NULL) &&
5801 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5802 attrs = attrs->next;
5803 continue;
5804 }
5805 if (ctxt->attrNr >= ctxt->attrMax) {
5806 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00005807
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 ctxt->attrMax *= 2;
5809 tmp = (xmlSchemaAttrStatePtr)
5810 xmlRealloc(ctxt->attr, ctxt->attrMax *
5811 sizeof(xmlSchemaAttrState));
5812 if (tmp == NULL) {
5813 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5814 ctxt->attrMax /= 2;
5815 return (-1);
5816 }
5817 ctxt->attr = tmp;
5818 }
5819 ctxt->attr[ctxt->attrNr].attr = attrs;
5820 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5821 ctxt->attrNr++;
5822 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005823 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005824 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005825}
5826
5827/**
5828 * xmlSchemaCheckAttributes:
5829 * @ctxt: a schema validation context
5830 * @node: the node carrying it.
5831 *
5832 * Check that the registered set of attributes on the current node
5833 * has been properly validated.
5834 *
5835 * Returns 0 if validity constraints are met, 1 otherwise.
5836 */
5837static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005838xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5839{
Daniel Veillard4255d502002-04-16 15:50:10 +00005840 int ret = 0;
5841 int i;
5842
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005843 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5844 if (ctxt->attr[i].attr == NULL)
5845 break;
5846 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5847 ret = 1;
William M. Bracke7091952004-05-11 15:09:58 +00005848 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
5849 "Attribute %s on %s is unknown\n",
5850 ctxt->attr[i].attr->name, node->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005851 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005852 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005853 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005854}
5855
William M. Brack29aa7722004-05-12 00:27:56 +00005856#if 0 /* Not currently used - remove if ever needed */
Daniel Veillard4255d502002-04-16 15:50:10 +00005857/**
5858 * xmlSchemaValidateSimpleContent:
5859 * @ctxt: a schema validation context
5860 * @elem: an element
5861 * @type: the type declaration
5862 *
5863 * Validate the content of an element expected to be a simple type
5864 *
5865 * Returns 0 if the element is schemas valid, a positive error code
5866 * number otherwise and -1 in case of internal or API error.
5867 */
5868static int
5869xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005870 xmlNodePtr node ATTRIBUTE_UNUSED)
5871{
Daniel Veillard4255d502002-04-16 15:50:10 +00005872 xmlNodePtr child;
5873 xmlSchemaTypePtr type, base;
5874 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005875 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005876
5877 child = ctxt->node;
5878 type = ctxt->type;
5879
5880 /*
5881 * Validation Rule: Element Locally Valid (Type): 3.1.3
5882 */
5883 value = xmlNodeGetContent(child);
5884 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5885 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005886 case XML_SCHEMA_TYPE_RESTRICTION:{
5887 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005888
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005889 base = type->baseType;
5890 if (base != NULL) {
5891 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5892 } else {
5893 TODO}
5894 if (ret == 0) {
5895 facet = type->facets;
5896 ret =
5897 xmlSchemaValidateFacets(ctxt, base, facet, value);
5898 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005899 if ((ret == 0) && (type->attributes != NULL)) {
5900 ret = xmlSchemaValidateAttributes(ctxt, node,
5901 type->attributes);
5902 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005903 break;
5904 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005905 case XML_SCHEMA_TYPE_EXTENSION:{
5906 TODO
5907 break;
5908 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005909 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005910 TODO
5911 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005912 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005913 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005914
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005915 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005916}
William M. Brack29aa7722004-05-12 00:27:56 +00005917#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00005918
5919/**
5920 * xmlSchemaValidateCheckNodeList
5921 * @nodelist: the list of nodes
5922 *
5923 * Check the node list is only made of text nodes and entities pointing
5924 * to text nodes
5925 *
5926 * Returns 1 if true, 0 if false and -1 in case of error
5927 */
5928static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005929xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5930{
Daniel Veillard4255d502002-04-16 15:50:10 +00005931 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005932 if (nodelist->type == XML_ENTITY_REF_NODE) {
5933 TODO /* implement recursion in the entity content */
5934 }
5935 if ((nodelist->type != XML_TEXT_NODE) &&
5936 (nodelist->type != XML_COMMENT_NODE) &&
5937 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +00005938 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005939 return (0);
5940 }
5941 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005942 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005943 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005944}
5945
5946/**
5947 * xmlSchemaSkipIgnored:
5948 * @ctxt: a schema validation context
5949 * @type: the current type context
5950 * @node: the top node.
5951 *
5952 * Skip ignorable nodes in that context
5953 *
5954 * Returns the new sibling
5955 * number otherwise and -1 in case of internal or API error.
5956 */
5957static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005958xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005959 xmlSchemaTypePtr type, xmlNodePtr node)
5960{
Daniel Veillard4255d502002-04-16 15:50:10 +00005961 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005962
Daniel Veillard4255d502002-04-16 15:50:10 +00005963 /*
5964 * TODO complete and handle entities
5965 */
5966 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005967 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005968 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005969 ((node->type == XML_COMMENT_NODE) ||
5970 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5971 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5972 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5973 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005974 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005975 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005976}
5977
5978/**
5979 * xmlSchemaValidateCallback:
5980 * @ctxt: a schema validation context
5981 * @name: the name of the element detected (might be NULL)
5982 * @type: the type
5983 *
5984 * A transition has been made in the automata associated to an element
5985 * content model
5986 */
5987static void
5988xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005989 const xmlChar * name ATTRIBUTE_UNUSED,
5990 xmlSchemaTypePtr type, xmlNodePtr node)
5991{
Daniel Veillard4255d502002-04-16 15:50:10 +00005992 xmlSchemaTypePtr oldtype = ctxt->type;
5993 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005994
Daniel Veillard4255d502002-04-16 15:50:10 +00005995#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00005996 xmlGenericError(xmlGenericErrorContext,
5997 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005998 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005999#endif
6000 ctxt->type = type;
6001 ctxt->node = node;
6002 xmlSchemaValidateContent(ctxt, node);
6003 ctxt->type = oldtype;
6004 ctxt->node = oldnode;
6005}
6006
6007
6008#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006009
Daniel Veillard4255d502002-04-16 15:50:10 +00006010/**
6011 * xmlSchemaValidateSimpleRestrictionType:
6012 * @ctxt: a schema validation context
6013 * @node: the top node.
6014 *
6015 * Validate the content of a restriction type.
6016 *
6017 * Returns 0 if the element is schemas valid, a positive error code
6018 * number otherwise and -1 in case of internal or API error.
6019 */
6020static int
6021xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
6022 xmlNodePtr node)
6023{
6024 xmlNodePtr child;
6025 xmlSchemaTypePtr type;
6026 int ret;
6027
6028 child = ctxt->node;
6029 type = ctxt->type;
6030
6031 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006032 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6033 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
6034 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006035 return (-1);
6036 }
6037 /*
6038 * Only text and text based entities references shall be found there
6039 */
6040 ret = xmlSchemaValidateCheckNodeList(child);
6041 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006042 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6043 "Internal error: xmlSchemaValidateSimpleType %s content\n",
6044 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006045 return (-1);
6046 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006047 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
6048 "Element %s content is not a simple type\n",
6049 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006050 return (-1);
6051 }
6052 ctxt->type = type->subtypes;
6053 xmlSchemaValidateContent(ctxt, node);
6054 ctxt->type = type;
6055 return (ret);
6056}
6057#endif
6058
6059/**
6060 * xmlSchemaValidateSimpleType:
6061 * @ctxt: a schema validation context
6062 * @node: the top node.
6063 *
6064 * Validate the content of an simple type.
6065 *
6066 * Returns 0 if the element is schemas valid, a positive error code
6067 * number otherwise and -1 in case of internal or API error.
6068 */
6069static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006070xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6071{
Daniel Veillard4255d502002-04-16 15:50:10 +00006072 xmlNodePtr child;
William M. Bracke7091952004-05-11 15:09:58 +00006073 xmlSchemaTypePtr type, base, variety;
Daniel Veillard4255d502002-04-16 15:50:10 +00006074 xmlAttrPtr attr;
6075 int ret;
William M. Bracke7091952004-05-11 15:09:58 +00006076 xmlChar *value;
6077
Daniel Veillard4255d502002-04-16 15:50:10 +00006078
6079 child = ctxt->node;
6080 type = ctxt->type;
6081
6082 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006083 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6084 "Internal error: xmlSchemaValidateSimpleType %s\n",
6085 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006086 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006087 }
6088 /*
6089 * Only text and text based entities references shall be found there
6090 */
6091 ret = xmlSchemaValidateCheckNodeList(child);
6092 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006093 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6094 "Internal error: xmlSchemaValidateSimpleType %s content\n",
6095 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006096 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006097 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006098 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
6099 "Element %s content is not a simple type\n",
6100 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006101 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006102 }
6103 /*
6104 * Validation Rule: Element Locally Valid (Type): 3.1.1
William M. Bracke7091952004-05-11 15:09:58 +00006105 */
6106
Daniel Veillard4255d502002-04-16 15:50:10 +00006107 attr = node->properties;
6108 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006109 if ((attr->ns == NULL) ||
6110 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
6111 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6112 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
6113 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
6114 (!xmlStrEqual
6115 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
William M. Bracke7091952004-05-11 15:09:58 +00006116 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
6117 "Element %s: attribute %s should not be present\n",
6118 node->name, attr->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006119 return (ctxt->err);
6120 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006121 }
William M. Bracke7091952004-05-11 15:09:58 +00006122 /* TODO:
6123 * If {variety} is ·atomic· then the {variety} of {base type definition}
6124 * must be ·atomic·.
6125 * If {variety} is ·list· then the {variety} of {item type definition}
6126 * must be either ·atomic· or ·union·.
6127 * If {variety} is ·union· then {member type definitions} must be a list
6128 * of datatype definitions.
6129 */
6130 if (type->subtypes == NULL) {
6131 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6132 "Internal error: xmlSchemaValidateSimpleType; "
6133 "simple type %s does not define a variety\n",
6134 node->name, NULL);
6135 return (ctxt->err);
6136 }
6137 /* Varieties: Restriction or List or Union. */
6138 variety = type->subtypes;
6139 ctxt->type = variety;
6140 value = xmlNodeGetContent(child);
6141 switch (variety->type) {
6142 case XML_SCHEMA_TYPE_RESTRICTION:{
6143 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00006144
William M. Bracke7091952004-05-11 15:09:58 +00006145 base = variety->baseType;
6146 if (base != NULL) {
6147 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
6148 } else {
6149 TODO}
6150 if (ret == 0) {
6151 facet = variety->facets;
6152 ret =
6153 xmlSchemaValidateFacets(ctxt, base, facet, value);
6154 }
6155 if ((ret == 0) && (variety->attributes != NULL)) {
6156 ret = xmlSchemaValidateAttributes(ctxt, node,
6157 variety->attributes);
6158 }
6159 break;
6160 }
6161 case XML_SCHEMA_TYPE_LIST:
6162 case XML_SCHEMA_TYPE_UNION: {
6163 ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
6164 break;
6165 }
6166 default:{
6167 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6168 "Internal error: xmlSchemaValidateSimpleType; "
6169 "simple type %s defines unknown content: %s\n",
6170 variety->name, NULL);
6171 ret = ctxt->err;
6172 }
6173 }
6174 if (value != NULL)
6175 xmlFree(value);
6176
6177 /* This was removed, since a simple content is not a content of a
6178 * simple type, but of a complex type.
6179 * ret = xmlSchemaValidateSimpleContent(ctxt, node);
6180 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006181 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006182 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006183}
6184
6185/**
6186 * xmlSchemaValidateElementType:
6187 * @ctxt: a schema validation context
6188 * @node: the top node.
6189 *
6190 * Validate the content of an element type.
6191 * Validation Rule: Element Locally Valid (Complex Type)
6192 *
6193 * Returns 0 if the element is schemas valid, a positive error code
6194 * number otherwise and -1 in case of internal or API error.
6195 */
6196static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006197xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6198{
Daniel Veillard4255d502002-04-16 15:50:10 +00006199 xmlNodePtr child;
6200 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006201 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 xmlSchemaElementPtr decl;
6203 int ret, attrBase;
6204
6205 oldregexp = ctxt->regexp;
6206
6207 child = ctxt->node;
6208 type = ctxt->type;
6209
6210 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006211 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6212 "Internal error: xmlSchemaValidateElementType\n",
6213 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006214 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006215 }
6216 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006217 if (type->minOccurs > 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006218 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
6219 "Element %s: missing child %s\n",
6220 node->name, type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006221 }
6222 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006223 }
6224
6225 /*
6226 * Verify the element matches
6227 */
6228 if (!xmlStrEqual(child->name, type->name)) {
William M. Bracke7091952004-05-11 15:09:58 +00006229 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
6230 "Element %s: missing child %s found %s\n",
6231 node->name, type->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006232 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006233 }
6234 /*
6235 * Verify the attributes
6236 */
6237 attrBase = ctxt->attrBase;
6238 ctxt->attrBase = ctxt->attrNr;
6239 xmlSchemaRegisterAttributes(ctxt, child->properties);
6240 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
6241 /*
6242 * Verify the element content recursively
6243 */
6244 decl = (xmlSchemaElementPtr) type;
6245 oldregexp = ctxt->regexp;
6246 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006247 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
6248 (xmlRegExecCallbacks)
6249 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006250#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006251 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006252#endif
6253 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006254 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
6255 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00006256
6257 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006258 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006259#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006260 xmlGenericError(xmlGenericErrorContext,
6261 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006262#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006263 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006264 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
6265 "Element %s content check failed\n",
6266 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006267 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006268 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
6269 "Element %s content check failure\n",
6270 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006271#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006272 } else {
6273 xmlGenericError(xmlGenericErrorContext,
6274 "Element %s content check succeeded\n",
6275 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006276
6277#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006278 }
6279 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006280 }
6281 /*
6282 * Verify that all attributes were Schemas-validated
6283 */
6284 xmlSchemaCheckAttributes(ctxt, node);
6285 ctxt->attrNr = ctxt->attrBase;
6286 ctxt->attrBase = attrBase;
6287
6288 ctxt->regexp = oldregexp;
6289
6290 ctxt->node = child;
6291 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006292 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006293}
6294
6295/**
6296 * xmlSchemaValidateBasicType:
6297 * @ctxt: a schema validation context
6298 * @node: the top node.
6299 *
6300 * Validate the content of an element expected to be a basic type type
6301 *
6302 * Returns 0 if the element is schemas valid, a positive error code
6303 * number otherwise and -1 in case of internal or API error.
6304 */
6305static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006306xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6307{
Daniel Veillard4255d502002-04-16 15:50:10 +00006308 int ret;
6309 xmlNodePtr child, cur;
6310 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006311 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00006312
6313 child = ctxt->node;
6314 type = ctxt->type;
6315
6316 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006317 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6318 "Internal error: xmlSchemaValidateBasicType\n",
6319 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006320 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006321 }
6322 /*
6323 * First check the content model of the node.
6324 */
6325 cur = child;
6326 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006327 switch (cur->type) {
6328 case XML_TEXT_NODE:
6329 case XML_CDATA_SECTION_NODE:
6330 case XML_PI_NODE:
6331 case XML_COMMENT_NODE:
6332 case XML_XINCLUDE_START:
6333 case XML_XINCLUDE_END:
6334 break;
6335 case XML_ENTITY_REF_NODE:
6336 case XML_ENTITY_NODE:
6337 TODO break;
6338 case XML_ELEMENT_NODE:
William M. Bracke7091952004-05-11 15:09:58 +00006339 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
6340 "Element %s: child %s should not be present\n",
6341 node->name, cur->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006342 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006343 case XML_ATTRIBUTE_NODE:
6344 case XML_DOCUMENT_NODE:
6345 case XML_DOCUMENT_TYPE_NODE:
6346 case XML_DOCUMENT_FRAG_NODE:
6347 case XML_NOTATION_NODE:
6348 case XML_HTML_DOCUMENT_NODE:
6349 case XML_DTD_NODE:
6350 case XML_ELEMENT_DECL:
6351 case XML_ATTRIBUTE_DECL:
6352 case XML_ENTITY_DECL:
6353 case XML_NAMESPACE_DECL:
6354#ifdef LIBXML_DOCB_ENABLED
6355 case XML_DOCB_DOCUMENT_NODE:
6356#endif
William M. Bracke7091952004-05-11 15:09:58 +00006357 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
6358 "Element %s: node type of node unexpected here\n",
6359 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006360 return (ctxt->err);
6361 }
6362 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006363 }
6364 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006365 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006366 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006367 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00006368
6369 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006370 xmlSchemaFreeValue(ctxt->value);
6371 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006372 }
6373 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
6374 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006375 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00006376 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006377 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
6378 "Element %s: failed to validate basic type %s\n",
6379 node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006380 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006381 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006382}
6383
6384/**
6385 * xmlSchemaValidateComplexType:
6386 * @ctxt: a schema validation context
6387 * @node: the top node.
6388 *
6389 * Validate the content of an element expected to be a complex type type
6390 * xmlschema-1.html#cvc-complex-type
6391 * Validation Rule: Element Locally Valid (Complex Type)
6392 *
6393 * Returns 0 if the element is schemas valid, a positive error code
6394 * number otherwise and -1 in case of internal or API error.
6395 */
6396static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006397xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6398{
Daniel Veillard4255d502002-04-16 15:50:10 +00006399 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00006400 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006401 int ret;
6402
6403 child = ctxt->node;
6404 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006405 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00006406
Daniel Veillard4255d502002-04-16 15:50:10 +00006407 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006408 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006409 if (type->baseType != NULL) {
6410 } else if (child != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006411 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY,
6412 "Element %s is supposed to be empty\n",
6413 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006414 }
6415 if (type->attributes != NULL) {
6416 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6417 }
6418 subtype = type->subtypes;
6419 while (subtype != NULL) {
6420 ctxt->type = subtype;
6421 xmlSchemaValidateComplexType(ctxt, node);
6422 subtype = subtype->next;
6423 }
6424 break;
6425 case XML_SCHEMA_CONTENT_ELEMENTS:
6426 case XML_SCHEMA_CONTENT_MIXED:
6427 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
6428 /*
6429 * Skip ignorable nodes in that context
6430 */
6431 child = xmlSchemaSkipIgnored(ctxt, type, child);
6432 while (child != NULL) {
6433 if (child->type == XML_ELEMENT_NODE) {
6434 ret = xmlRegExecPushString(ctxt->regexp,
6435 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00006436#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006437 if (ret < 0)
6438 xmlGenericError(xmlGenericErrorContext,
6439 " --> %s Error\n", child->name);
6440 else
6441 xmlGenericError(xmlGenericErrorContext,
6442 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006443#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006444 }
6445 child = child->next;
6446 /*
6447 * Skip ignorable nodes in that context
6448 */
6449 child = xmlSchemaSkipIgnored(ctxt, type, child);
6450 }
William M. Bracke7091952004-05-11 15:09:58 +00006451 if (((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
6452 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS)) &&
6453 (type->subtypes != NULL)) {
6454 TODO
6455 }
6456
6457
Daniel Veillardf2a12832003-11-24 13:04:35 +00006458 if (type->attributes != NULL) {
6459 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6460 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006461 break;
6462 case XML_SCHEMA_CONTENT_BASIC:{
6463 if (type->subtypes != NULL) {
6464 ctxt->type = type->subtypes;
6465 xmlSchemaValidateComplexType(ctxt, node);
6466 }
6467 if (type->baseType != NULL) {
6468 ctxt->type = type->baseType;
William M. Bracke7091952004-05-11 15:09:58 +00006469 if (type->baseType->type == XML_SCHEMA_TYPE_BASIC)
6470 xmlSchemaValidateBasicType(ctxt, node);
6471 else if (type->baseType->type == XML_SCHEMA_TYPE_COMPLEX)
6472 xmlSchemaValidateComplexType(ctxt, node);
6473 else if (type->baseType->type == XML_SCHEMA_TYPE_SIMPLE)
6474 xmlSchemaValidateSimpleType(ctxt, node);
6475 else
6476 xmlGenericError(xmlGenericErrorContext,
6477 "unexpected content type of base: %d\n",
6478 type->contentType);
6479
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006480 }
6481 if (type->attributes != NULL) {
6482 xmlSchemaValidateAttributes(ctxt, node,
6483 type->attributes);
6484 }
6485 ctxt->type = type;
6486 break;
6487 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006488 case XML_SCHEMA_CONTENT_SIMPLE:{
6489 if (type->subtypes != NULL) {
6490 ctxt->type = type->subtypes;
6491 xmlSchemaValidateComplexType(ctxt, node);
6492 }
6493 if (type->baseType != NULL) {
6494 ctxt->type = type->baseType;
6495 xmlSchemaValidateComplexType(ctxt, node);
6496 }
6497 if (type->attributes != NULL) {
6498 xmlSchemaValidateAttributes(ctxt, node,
6499 type->attributes);
6500 }
6501 ctxt->type = type;
6502 break;
6503 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006504 default:
6505 TODO xmlGenericError(xmlGenericErrorContext,
6506 "unimplemented content type %d\n",
6507 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006508 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006509 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006510}
6511
6512/**
6513 * xmlSchemaValidateContent:
6514 * @ctxt: a schema validation context
6515 * @elem: an element
6516 * @type: the type declaration
6517 *
6518 * Validate the content of an element against the type.
6519 *
6520 * Returns 0 if the element is schemas valid, a positive error code
6521 * number otherwise and -1 in case of internal or API error.
6522 */
6523static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006524xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6525{
Daniel Veillard4255d502002-04-16 15:50:10 +00006526 xmlNodePtr child;
6527 xmlSchemaTypePtr type;
6528
6529 child = ctxt->node;
6530 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006531 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00006532
Daniel Veillarde19fc232002-04-22 16:01:24 +00006533 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006534 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00006535
Daniel Veillard4255d502002-04-16 15:50:10 +00006536 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006537 case XML_SCHEMA_TYPE_ANY:
6538 /* Any type will do it, fine */
6539 TODO /* handle recursivity */
6540 break;
6541 case XML_SCHEMA_TYPE_COMPLEX:
6542 xmlSchemaValidateComplexType(ctxt, node);
6543 break;
6544 case XML_SCHEMA_TYPE_ELEMENT:{
6545 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
6546
6547 /*
6548 * Handle element reference here
6549 */
6550 if (decl->ref != NULL) {
6551 if (decl->refDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006552 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
6553 "Internal error: element reference %s "
6554 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006555 return (-1);
6556 }
6557 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
6558 decl = decl->refDecl;
6559 }
William M. Bracke7091952004-05-11 15:09:58 +00006560 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006561 xmlSchemaValidateElementType(ctxt, node);
6562 ctxt->type = type;
6563 break;
6564 }
6565 case XML_SCHEMA_TYPE_BASIC:
6566 xmlSchemaValidateBasicType(ctxt, node);
6567 break;
6568 case XML_SCHEMA_TYPE_FACET:
6569 TODO break;
6570 case XML_SCHEMA_TYPE_SIMPLE:
6571 xmlSchemaValidateSimpleType(ctxt, node);
6572 break;
6573 case XML_SCHEMA_TYPE_SEQUENCE:
6574 TODO break;
6575 case XML_SCHEMA_TYPE_CHOICE:
6576 TODO break;
6577 case XML_SCHEMA_TYPE_ALL:
6578 TODO break;
6579 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
6580 TODO break;
6581 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
6582 TODO break;
6583 case XML_SCHEMA_TYPE_UR:
6584 TODO break;
6585 case XML_SCHEMA_TYPE_RESTRICTION:
6586 /*xmlSchemaValidateRestrictionType(ctxt, node); */
6587 TODO break;
6588 case XML_SCHEMA_TYPE_EXTENSION:
6589 TODO break;
6590 case XML_SCHEMA_TYPE_ATTRIBUTE:
6591 TODO break;
6592 case XML_SCHEMA_TYPE_GROUP:
6593 TODO break;
6594 case XML_SCHEMA_TYPE_NOTATION:
6595 TODO break;
6596 case XML_SCHEMA_TYPE_LIST:
6597 TODO break;
6598 case XML_SCHEMA_TYPE_UNION:
6599 TODO break;
6600 case XML_SCHEMA_FACET_MININCLUSIVE:
6601 TODO break;
6602 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6603 TODO break;
6604 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6605 TODO break;
6606 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
6607 TODO break;
6608 case XML_SCHEMA_FACET_TOTALDIGITS:
6609 TODO break;
6610 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6611 TODO break;
6612 case XML_SCHEMA_FACET_PATTERN:
6613 TODO break;
6614 case XML_SCHEMA_FACET_ENUMERATION:
6615 TODO break;
6616 case XML_SCHEMA_FACET_WHITESPACE:
6617 TODO break;
6618 case XML_SCHEMA_FACET_LENGTH:
6619 TODO break;
6620 case XML_SCHEMA_FACET_MAXLENGTH:
6621 TODO break;
6622 case XML_SCHEMA_FACET_MINLENGTH:
6623 TODO break;
6624 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
6625 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +00006626 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6627 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00006628 }
6629 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6630
6631 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006632 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006633 ctxt->node = ctxt->node->next;
6634 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006635 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006636}
6637
6638/**
6639 * xmlSchemaValidateType:
6640 * @ctxt: a schema validation context
6641 * @elem: an element
6642 * @type: the list of type declarations
6643 *
6644 * Validate the content of an element against the types.
6645 *
6646 * Returns 0 if the element is schemas valid, a positive error code
6647 * number otherwise and -1 in case of internal or API error.
6648 */
6649static int
6650xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006651 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
6652{
Daniel Veillard4255d502002-04-16 15:50:10 +00006653 xmlChar *nil;
6654
Daniel Veillard2db8c122003-07-08 12:16:59 +00006655 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006656 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00006657
Daniel Veillard4255d502002-04-16 15:50:10 +00006658 /*
6659 * 3.3.4 : 2
6660 */
6661 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
William M. Bracke7091952004-05-11 15:09:58 +00006662 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
6663 "Element declaration %s is abstract\n",
6664 elemDecl->name, NULL);
6665 /* Changed, since the element declaration is abstract and not
6666 * the element itself. */
6667 /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
6668 "Element %s is abstract\n", elem->name, NULL); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006669 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006670 }
6671 /*
6672 * 3.3.4: 3
6673 */
6674 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
6675 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006676 /* 3.3.4: 3.2 */
6677 if (xmlStrEqual(nil, BAD_CAST "true")) {
6678 if (elem->children != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006679 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
6680 "Element %s is not empty\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006681 return (ctxt->err);
6682 }
6683 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
6684 (elemDecl->value != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00006685 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
6686 "Empty element %s cannot get a fixed value\n",
6687 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006688 return (ctxt->err);
6689 }
6690 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006691 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006692 /* 3.3.4: 3.1 */
6693 if (nil != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006694 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
6695 "Element %s with xs:nil but not nillable\n",
6696 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006697 xmlFree(nil);
6698 return (ctxt->err);
6699 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006700 }
6701
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006702 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00006703
6704 ctxt->type = elemDecl->subtypes;
6705 ctxt->node = elem->children;
6706 xmlSchemaValidateContent(ctxt, elem);
6707 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006708
6709 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006710}
6711
6712
6713/**
6714 * xmlSchemaValidateAttributes:
6715 * @ctxt: a schema validation context
6716 * @elem: an element
6717 * @attributes: the list of attribute declarations
6718 *
6719 * Validate the attributes of an element.
6720 *
6721 * Returns 0 if the element is schemas valid, a positive error code
6722 * number otherwise and -1 in case of internal or API error.
6723 */
6724static int
6725xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006726 xmlSchemaAttributePtr attributes)
6727{
William M. Brack87640d52004-04-17 14:58:15 +00006728 int i, ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006729 xmlAttrPtr attr;
6730 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006731 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006732 int found;
Daniel Veillard4255d502002-04-16 15:50:10 +00006733
6734 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006735 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006736 while (attributes != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006737 found = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006738 /*
6739 * Handle attribute groups
6740 */
6741 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6742 group = (xmlSchemaAttributeGroupPtr) attributes;
6743 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6744 attributes = group->next;
6745 continue;
6746 }
6747 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6748 attr = ctxt->attr[i].attr;
6749 if (attr == NULL)
6750 continue;
6751 if (attributes->ref != NULL) {
6752 if (!xmlStrEqual(attr->name, attributes->ref))
6753 continue;
6754 if (attr->ns != NULL) {
6755 if ((attributes->refNs == NULL) ||
6756 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6757 continue;
6758 } else if (attributes->refNs != NULL) {
6759 continue;
6760 }
6761 } else {
6762 if (!xmlStrEqual(attr->name, attributes->name))
6763 continue;
6764 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006765 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006766 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006767 if (attr->ns == NULL) {
6768 /*
William M. Bracke7091952004-05-11 15:09:58 +00006769 * accept an unqualified attribute only if the target
6770 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006771 */
William M. Bracke7091952004-05-11 15:09:58 +00006772 if (attributes->targetNamespace != NULL)
6773 /*
6774 * This check was removed, since the target namespace
6775 * was evaluated during parsing and already took
6776 * "attributeFormDefault" into account.
6777 */
6778 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006779 continue;
6780 } else {
6781 if (attributes->targetNamespace == NULL)
6782 continue;
6783 if (!xmlStrEqual(attributes->targetNamespace,
6784 attr->ns->href))
6785 continue;
6786 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006787 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006788 found = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006789 ctxt->cur = (xmlNodePtr) attributes;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006790
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006791 if (attributes->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006792 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
6793 "Internal error: attribute %s type not resolved\n",
6794 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006795 continue;
6796 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006797
6798 if (attributes->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
William M. Bracke7091952004-05-11 15:09:58 +00006799 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INVALIDATTR,
6800 "attribute %s on %s is prohibited\n",
6801 attributes->name, elem->name);
6802 /* Setting the state to XML_SCHEMAS_ATTR_CHECKED seems
6803 * not very logical but it suppresses the
6804 * "attribute is unknown" error report. Please change
6805 * this if you know better */
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006806 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6807 break;
6808 }
6809
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006810 value = xmlNodeListGetString(elem->doc, attr->children, 1);
6811 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6812 value);
6813 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006814 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
6815 XML_SCHEMAS_ERR_ATTRINVALID,
6816 "attribute %s on %s does not match type\n",
6817 attr->name, elem->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006818 } else {
6819 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6820 }
6821 if (value != NULL) {
6822 xmlFree(value);
6823 }
6824 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006825 if ((!found) && (attributes->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
William M. Bracke7091952004-05-11 15:09:58 +00006826 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_MISSING,
6827 "required attribute %s on %s is missing\n",
6828 attributes->name, elem->name);
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006829 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006830 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006831 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006832 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006833}
6834
6835/**
6836 * xmlSchemaValidateElement:
6837 * @ctxt: a schema validation context
6838 * @elem: an element
6839 *
6840 * Validate an element in a tree
6841 *
6842 * Returns 0 if the element is schemas valid, a positive error code
6843 * number otherwise and -1 in case of internal or API error.
6844 */
6845static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006846xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6847{
Daniel Veillard4255d502002-04-16 15:50:10 +00006848 xmlSchemaElementPtr elemDecl;
6849 int ret, attrBase;
6850
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006851 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006852 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6853 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006854 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006855 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6856 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006857 }
6858 /*
6859 * special case whe elementFormDefault is unqualified for top-level elem.
6860 */
William M. Bracke7091952004-05-11 15:09:58 +00006861 /*
6862 * This was removed, since elementFormDefault does not apply to top-level
6863 * element declarations.
6864 */
6865 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006866 if ((elemDecl == NULL) && (elem->ns != NULL) &&
6867 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6868 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6869 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6870 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6871 elem->name, NULL, NULL);
6872 }
William M. Bracke7091952004-05-11 15:09:58 +00006873 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006874
Daniel Veillard4255d502002-04-16 15:50:10 +00006875 /*
6876 * 3.3.4 : 1
6877 */
6878 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006879 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
6880 "Element %s not declared\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006881 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006882 }
6883 if (elemDecl->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006884 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
6885 "Element %s has no type\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006886 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006887 }
6888 /*
6889 * Verify the attributes
6890 */
6891 attrBase = ctxt->attrBase;
6892 ctxt->attrBase = ctxt->attrNr;
6893 xmlSchemaRegisterAttributes(ctxt, elem->properties);
6894 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6895 /*
6896 * Verify the element content recursively
6897 */
6898 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006899 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6900 (xmlRegExecCallbacks)
6901 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006902#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006903 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006904#endif
6905 }
6906 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006907 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006908 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006909#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006910 xmlGenericError(xmlGenericErrorContext,
6911 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006912#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006913 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006914 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
6915 "Element %s content check failed\n",
6916 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006917 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006918 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
6919 "Element %s content check failed\n",
6920 elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006921#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006922 } else {
6923 xmlGenericError(xmlGenericErrorContext,
6924 "Element %s content check succeeded\n",
6925 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006926
6927#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006928 }
6929 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006930 }
6931 /*
6932 * Verify that all attributes were Schemas-validated
6933 */
6934 xmlSchemaCheckAttributes(ctxt, elem);
6935 ctxt->attrNr = ctxt->attrBase;
6936 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006937
6938 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006939}
6940
6941/**
6942 * xmlSchemaValidateDocument:
6943 * @ctxt: a schema validation context
6944 * @doc: a parsed document tree
6945 *
6946 * Validate a document tree in memory.
6947 *
6948 * Returns 0 if the document is schemas valid, a positive error code
6949 * number otherwise and -1 in case of internal or API error.
6950 */
6951static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006952xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6953{
Daniel Veillard4255d502002-04-16 15:50:10 +00006954 xmlNodePtr root;
6955 xmlSchemaElementPtr elemDecl;
6956
6957 root = xmlDocGetRootElement(doc);
6958 if (root == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006959 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
6960 "document has no root\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006961 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006962 }
William M. Bracke7091952004-05-11 15:09:58 +00006963
Daniel Veillard4255d502002-04-16 15:50:10 +00006964 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006965 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6966 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006967 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006968 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6969 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006970 /*
6971 * special case whe elementFormDefault is unqualified for top-level elem.
6972 */
6973 if ((elemDecl == NULL) && (root->ns != NULL) &&
6974 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
6975 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6976 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6977 root->name, NULL, NULL);
6978 }
6979
Daniel Veillard4255d502002-04-16 15:50:10 +00006980 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006981 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
6982 "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006983 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00006984 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
6985 "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006986 }
6987 /*
6988 * Okay, start the recursive validation
6989 */
6990 xmlSchemaValidateElement(ctxt, root);
6991
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006992 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006993}
6994
6995/************************************************************************
6996 * *
6997 * SAX Validation code *
6998 * *
6999 ************************************************************************/
7000
7001/************************************************************************
7002 * *
7003 * Validation interfaces *
7004 * *
7005 ************************************************************************/
7006
7007/**
7008 * xmlSchemaNewValidCtxt:
7009 * @schema: a precompiled XML Schemas
7010 *
7011 * Create an XML Schemas validation context based on the given schema
7012 *
7013 * Returns the validation context or NULL in case of error
7014 */
7015xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007016xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
7017{
Daniel Veillard4255d502002-04-16 15:50:10 +00007018 xmlSchemaValidCtxtPtr ret;
7019
7020 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
7021 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007022 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007023 return (NULL);
7024 }
7025 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
7026 ret->schema = schema;
7027 ret->attrNr = 0;
7028 ret->attrMax = 10;
7029 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007030 sizeof
7031 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00007032 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007033 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
7034 free(ret);
7035 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007036 }
7037 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
7038 return (ret);
7039}
7040
7041/**
7042 * xmlSchemaFreeValidCtxt:
7043 * @ctxt: the schema validation context
7044 *
7045 * Free the resources associated to the schema validation context
7046 */
7047void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007048xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
7049{
Daniel Veillard4255d502002-04-16 15:50:10 +00007050 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007051 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007052 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007053 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00007054 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007055 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00007056 xmlFree(ctxt);
7057}
7058
7059/**
7060 * xmlSchemaSetValidErrors:
7061 * @ctxt: a schema validation context
7062 * @err: the error function
7063 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00007064 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00007065 *
7066 * Set the error and warning callback informations
7067 */
7068void
7069xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007070 xmlSchemaValidityErrorFunc err,
7071 xmlSchemaValidityWarningFunc warn, void *ctx)
7072{
Daniel Veillard4255d502002-04-16 15:50:10 +00007073 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007074 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007075 ctxt->error = err;
7076 ctxt->warning = warn;
7077 ctxt->userData = ctx;
7078}
7079
7080/**
7081 * xmlSchemaValidateDoc:
7082 * @ctxt: a schema validation context
7083 * @doc: a parsed document tree
7084 *
7085 * Validate a document tree in memory.
7086 *
7087 * Returns 0 if the document is schemas valid, a positive error code
7088 * number otherwise and -1 in case of internal or API error.
7089 */
7090int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007091xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
7092{
Daniel Veillard4255d502002-04-16 15:50:10 +00007093 int ret;
7094
7095 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007096 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007097
7098 ctxt->doc = doc;
7099 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007100 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007101}
7102
7103/**
7104 * xmlSchemaValidateStream:
7105 * @ctxt: a schema validation context
7106 * @input: the input to use for reading the data
7107 * @enc: an optional encoding information
7108 * @sax: a SAX handler for the resulting events
7109 * @user_data: the context to provide to the SAX handler.
7110 *
7111 * Validate a document tree in memory.
7112 *
7113 * Returns 0 if the document is schemas valid, a positive error code
7114 * number otherwise and -1 in case of internal or API error.
7115 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007116int
Daniel Veillard4255d502002-04-16 15:50:10 +00007117xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007118 xmlParserInputBufferPtr input, xmlCharEncoding enc,
7119 xmlSAXHandlerPtr sax, void *user_data)
7120{
Daniel Veillard4255d502002-04-16 15:50:10 +00007121 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007122 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007123 ctxt->input = input;
7124 ctxt->enc = enc;
7125 ctxt->sax = sax;
7126 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007127 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007128}
7129
7130#endif /* LIBXML_SCHEMAS_ENABLED */