blob: 9c9f17fe9dd278d6313e4952d75b98c027c9640b [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
Daniel Veillard3646d642004-06-02 19:19:14 +000045/* #define DEBUG_ATTR_VALIDATION 1 */
46
Daniel Veillard4255d502002-04-16 15:50:10 +000047#define UNBOUNDED (1 << 30)
48#define TODO \
49 xmlGenericError(xmlGenericErrorContext, \
50 "Unimplemented block at %s:%d\n", \
51 __FILE__, __LINE__);
52
Daniel Veillard5a872412002-05-22 06:40:27 +000053#define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
54
Daniel Veillard4255d502002-04-16 15:50:10 +000055/*
56 * The XML Schemas namespaces
57 */
58static const xmlChar *xmlSchemaNs = (const xmlChar *)
59 "http://www.w3.org/2001/XMLSchema";
60
61static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
62 "http://www.w3.org/2001/XMLSchema-instance";
63
64#define IS_SCHEMA(node, type) \
65 ((node != NULL) && (node->ns != NULL) && \
66 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
67 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
68
69#define XML_SCHEMAS_PARSE_ERROR 1
70
Daniel Veillardbd2904b2003-11-25 15:38:59 +000071#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
72
Daniel Veillard4255d502002-04-16 15:50:10 +000073struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000074 void *userData; /* user specific data block */
75 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
76 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +000077 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000078 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +000079 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +000080
Daniel Veillardbe9c6322003-11-22 20:37:51 +000081 xmlSchemaPtr topschema; /* The main schema */
82 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
83
Daniel Veillardd0c9c322003-10-10 00:49:42 +000084 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000085 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +000086 int counter;
87
Daniel Veillardbe9c6322003-11-22 20:37:51 +000088 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000089 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000090 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +000091
Daniel Veillardd0c9c322003-10-10 00:49:42 +000092 const char *buffer;
93 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +000094
Daniel Veillard4255d502002-04-16 15:50:10 +000095 /*
96 * Used to build complex element content models
97 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000098 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +000099 xmlAutomataStatePtr start;
100 xmlAutomataStatePtr end;
101 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000102
103 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000104 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard4255d502002-04-16 15:50:10 +0000105};
106
107
108#define XML_SCHEMAS_ATTR_UNKNOWN 1
109#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000110#define XML_SCHEMAS_ATTR_PROHIBITED 3
111#define XML_SCHEMAS_ATTR_MISSING 4
112#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
113#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Daniel Veillard4255d502002-04-16 15:50:10 +0000114
115typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
116typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
117struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000118 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000119 xmlAttrPtr attr;
120 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000121 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +0000122};
123
124/**
125 * xmlSchemaValidCtxt:
126 *
127 * A Schemas validation context
128 */
129
130struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000131 void *userData; /* user specific data block */
132 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
133 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000134 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000135
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000136 xmlSchemaPtr schema; /* The schema in use */
137 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000138 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000139 xmlCharEncoding enc;
140 xmlSAXHandlerPtr sax;
141 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000142
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000143 xmlDocPtr myDoc;
144 int err;
145 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000146
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000147 xmlNodePtr node;
148 xmlNodePtr cur;
149 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000150
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000151 xmlRegExecCtxtPtr regexp;
152 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000153
Daniel Veillard3646d642004-06-02 19:19:14 +0000154 xmlSchemaAttrStatePtr attrTop;
155 /* xmlSchemaAttrStatePtr attrBase; */
156 /* int attrMax; */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000157 xmlSchemaAttrStatePtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +0000158};
159
Daniel Veillard1d913862003-11-21 00:28:39 +0000160/*
161 * These are the entries in the schemas importSchemas hash table
162 */
163typedef struct _xmlSchemaImport xmlSchemaImport;
164typedef xmlSchemaImport *xmlSchemaImportPtr;
165struct _xmlSchemaImport {
166 const xmlChar *schemaLocation;
167 xmlSchemaPtr schema;
168};
Daniel Veillard4255d502002-04-16 15:50:10 +0000169
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000170/*
171 * These are the entries associated to includes in a schemas
172 */
173typedef struct _xmlSchemaInclude xmlSchemaInclude;
174typedef xmlSchemaInclude *xmlSchemaIncludePtr;
175struct _xmlSchemaInclude {
176 xmlSchemaIncludePtr next;
177
178 const xmlChar *schemaLocation;
179 xmlDocPtr doc;
180};
181
Daniel Veillard4255d502002-04-16 15:50:10 +0000182/************************************************************************
183 * *
184 * Some predeclarations *
185 * *
186 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000187static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
188 xmlSchemaTypePtr type,
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000189 const xmlChar * value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000190
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000191static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
192 xmlSchemaPtr schema,
193 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +0000194static int
195xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
196 xmlSchemaTypePtr type,
197 const xmlChar * value,
198 int fireErrors);
199
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000200/************************************************************************
201 * *
202 * Datatype error handlers *
203 * *
204 ************************************************************************/
205
206/**
207 * xmlSchemaPErrMemory:
208 * @node: a context node
209 * @extra: extra informations
210 *
211 * Handle an out of memory condition
212 */
213static void
214xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
215 const char *extra, xmlNodePtr node)
216{
217 if (ctxt != NULL)
218 ctxt->nberrors++;
219 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
220 extra);
221}
222
223/**
224 * xmlSchemaPErr:
225 * @ctxt: the parsing context
226 * @node: the context node
227 * @error: the error code
228 * @msg: the error message
229 * @str1: extra data
230 * @str2: extra data
231 *
232 * Handle a parser error
233 */
234static void
235xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
236 const char *msg, const xmlChar * str1, const xmlChar * str2)
237{
238 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000239 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000240 void *data = NULL;
241
242 if (ctxt != NULL) {
243 ctxt->nberrors++;
244 channel = ctxt->error;
245 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000246 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000247 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000248 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000249 error, XML_ERR_ERROR, NULL, 0,
250 (const char *) str1, (const char *) str2, NULL, 0, 0,
251 msg, str1, str2);
252}
253
254/**
255 * xmlSchemaPErr2:
256 * @ctxt: the parsing context
257 * @node: the context node
258 * @node: the current child
259 * @error: the error code
260 * @msg: the error message
261 * @str1: extra data
262 * @str2: extra data
263 *
264 * Handle a parser error
265 */
266static void
267xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
268 xmlNodePtr child, int error,
269 const char *msg, const xmlChar * str1, const xmlChar * str2)
270{
271 if (child != NULL)
272 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
273 else
274 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
275}
276
277/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000278 * xmlSchemaPErrExt:
279 * @ctxt: the parsing context
280 * @node: the context node
281 * @error: the error code
282 * @strData1: extra data
283 * @strData2: extra data
284 * @strData3: extra data
285 * @msg: the message
286 * @str1: extra parameter for the message display
287 * @str2: extra parameter for the message display
288 * @str3: extra parameter for the message display
289 * @str4: extra parameter for the message display
290 * @str5: extra parameter for the message display
291 *
292 * Handle a parser error
293 */
294static void
295xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
296 const xmlChar * strData1, const xmlChar * strData2,
297 const xmlChar * strData3, const char *msg, const xmlChar * str1,
298 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
299 const xmlChar * str5)
300{
301
302 xmlGenericErrorFunc channel = NULL;
303 xmlStructuredErrorFunc schannel = NULL;
304 void *data = NULL;
305
306 if (ctxt != NULL) {
307 ctxt->nberrors++;
308 channel = ctxt->error;
309 data = ctxt->userData;
310 schannel = ctxt->serror;
311 }
312 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
313 error, XML_ERR_ERROR, NULL, 0,
314 (const char *) strData1, (const char *) strData2,
315 (const char *) strData3, 0, 0, msg, str1, str2, str3, str4, str5);
316}
317
318/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000319 * xmlSchemaVTypeErrMemory:
320 * @node: a context node
321 * @extra: extra informations
322 *
323 * Handle an out of memory condition
324 */
325static void
326xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
327 const char *extra, xmlNodePtr node)
328{
329 if (ctxt != NULL) {
330 ctxt->nberrors++;
331 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
332 }
333 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
334 extra);
335}
336
337/**
338 * xmlSchemaVErr3:
339 * @ctxt: the validation context
340 * @node: the context node
341 * @error: the error code
342 * @msg: the error message
343 * @str1: extra data
344 * @str2: extra data
345 * @str3: extra data
346 *
347 * Handle a validation error
348 */
349static void
350xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
351 const char *msg, const xmlChar *str1, const xmlChar *str2,
352 const xmlChar *str3)
353{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000354 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000355 xmlGenericErrorFunc channel = NULL;
356 void *data = NULL;
357
358 if (ctxt != NULL) {
359 ctxt->nberrors++;
360 ctxt->err = error;
361 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000362 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000363 data = ctxt->userData;
364 }
365 /* reajust to global error numbers */
366 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000367 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000368 error, XML_ERR_ERROR, NULL, 0,
369 (const char *) str1, (const char *) str2,
370 (const char *) str3, 0, 0,
371 msg, str1, str2, str3);
372}
373/**
374 * xmlSchemaVErr:
375 * @ctxt: the validation context
376 * @node: the context node
377 * @error: the error code
378 * @msg: the error message
379 * @str1: extra data
380 * @str2: extra data
381 *
382 * Handle a validation error
383 */
384static void
385xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
386 const char *msg, const xmlChar * str1, const xmlChar * str2)
387{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000388 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000389 xmlGenericErrorFunc channel = NULL;
390 void *data = NULL;
391
392 if (ctxt != NULL) {
393 ctxt->nberrors++;
394 ctxt->err = error;
395 channel = ctxt->error;
396 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000397 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000398 }
399 /* reajust to global error numbers */
400 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000401 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000402 error, XML_ERR_ERROR, NULL, 0,
403 (const char *) str1, (const char *) str2, NULL, 0, 0,
404 msg, str1, str2);
405}
Daniel Veillard4255d502002-04-16 15:50:10 +0000406
407/************************************************************************
408 * *
409 * Allocation functions *
410 * *
411 ************************************************************************/
412
413/**
414 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +0000415 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000416 *
417 * Allocate a new Schema structure.
418 *
419 * Returns the newly allocated structure or NULL in case or error
420 */
421static xmlSchemaPtr
422xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
423{
424 xmlSchemaPtr ret;
425
426 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
427 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000428 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000429 return (NULL);
430 }
431 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000432 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000433 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000434
435 return (ret);
436}
437
438/**
439 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000440 *
441 * Allocate a new Facet structure.
442 *
443 * Returns the newly allocated structure or NULL in case or error
444 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000445xmlSchemaFacetPtr
446xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000447{
448 xmlSchemaFacetPtr ret;
449
450 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
451 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000452 return (NULL);
453 }
454 memset(ret, 0, sizeof(xmlSchemaFacet));
455
456 return (ret);
457}
458
459/**
460 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +0000461 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000462 * @node: a node
463 *
464 * Allocate a new annotation structure.
465 *
466 * Returns the newly allocated structure or NULL in case or error
467 */
468static xmlSchemaAnnotPtr
469xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
470{
471 xmlSchemaAnnotPtr ret;
472
473 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
474 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000475 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000476 return (NULL);
477 }
478 memset(ret, 0, sizeof(xmlSchemaAnnot));
479 ret->content = node;
480 return (ret);
481}
482
483/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000484 * xmlSchemaFreeAnnot:
485 * @annot: a schema type structure
486 *
487 * Deallocate a annotation structure
488 */
489static void
490xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
491{
492 if (annot == NULL)
493 return;
494 xmlFree(annot);
495}
496
497/**
Daniel Veillard1d913862003-11-21 00:28:39 +0000498 * xmlSchemaFreeImport:
499 * @import: a schema import structure
500 *
501 * Deallocate an import structure
502 */
503static void
504xmlSchemaFreeImport(xmlSchemaImportPtr import)
505{
506 if (import == NULL)
507 return;
508
509 xmlSchemaFree(import->schema);
Daniel Veillard1d913862003-11-21 00:28:39 +0000510 xmlFree(import);
511}
512
513/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000514 * xmlSchemaFreeInclude:
515 * @include: a schema include structure
516 *
517 * Deallocate an include structure
518 */
519static void
520xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
521{
522 if (include == NULL)
523 return;
524
525 xmlFreeDoc(include->doc);
526 xmlFree(include);
527}
528
529/**
530 * xmlSchemaFreeIncludeList:
531 * @includes: a schema include list
532 *
533 * Deallocate an include structure
534 */
535static void
536xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
537{
538 xmlSchemaIncludePtr next;
539
540 while (includes != NULL) {
541 next = includes->next;
542 xmlSchemaFreeInclude(includes);
543 includes = next;
544 }
545}
546
547/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000548 * xmlSchemaFreeNotation:
549 * @schema: a schema notation structure
550 *
551 * Deallocate a Schema Notation structure.
552 */
553static void
554xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
555{
556 if (nota == NULL)
557 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000558 xmlFree(nota);
559}
560
561/**
562 * xmlSchemaFreeAttribute:
563 * @schema: a schema attribute structure
564 *
565 * Deallocate a Schema Attribute structure.
566 */
567static void
568xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
569{
570 if (attr == NULL)
571 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000572 xmlFree(attr);
573}
574
575/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000576 * xmlSchemaFreeWildcardNsSet:
577 * set: a schema wildcard namespace
578 *
579 * Deallocate a list of wildcard constraint structures.
580 */
581static void
582xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
583{
584 xmlSchemaWildcardNsPtr next;
585
586 while (set != NULL) {
587 next = set->next;
588 xmlFree(set);
589 set = next;
590 }
591}
592
593/**
594 * xmlSchemaFreeWildcard:
595 * @schema: a schema attribute group structure
596 *
597 * Deallocate a Schema Attribute Group structure.
598 */
599static void
600xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
601{
602 if (wildcard == NULL)
603 return;
604 if (wildcard->annot != NULL)
605 xmlSchemaFreeAnnot(wildcard->annot);
606 if (wildcard->nsSet != NULL)
607 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
608 if (wildcard->negNsSet != NULL)
609 xmlFree(wildcard->negNsSet);
610 xmlFree(wildcard);
611}
612
613/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000614 * xmlSchemaFreeAttributeGroup:
615 * @schema: a schema attribute group structure
616 *
617 * Deallocate a Schema Attribute Group structure.
618 */
619static void
620xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
621{
622 if (attr == NULL)
623 return;
Daniel Veillard3646d642004-06-02 19:19:14 +0000624 if (attr->annot != NULL)
625 xmlSchemaFreeAnnot(attr->annot);
626 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
627 (attr->attributeWildcard != NULL))
628 xmlSchemaFreeWildcard(attr->attributeWildcard);
629
Daniel Veillard4255d502002-04-16 15:50:10 +0000630 xmlFree(attr);
631}
632
633/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000634 * xmlSchemaFreeAttributeUseList:
635 * @attrUse: a schema attribute link structure
636 *
637 * Deallocate a list of schema attribute uses.
638 */
639static void
640xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
641{
642 xmlSchemaAttributeLinkPtr next;
643
644 while (attrUse != NULL) {
645 next = attrUse->next;
646 xmlFree(attrUse);
647 attrUse = next;
648 }
649}
650
651/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000652 * xmlSchemaFreeElement:
653 * @schema: a schema element structure
654 *
655 * Deallocate a Schema Element structure.
656 */
657static void
658xmlSchemaFreeElement(xmlSchemaElementPtr elem)
659{
660 if (elem == NULL)
661 return;
Daniel Veillard32370232002-10-16 14:08:14 +0000662 if (elem->annot != NULL)
663 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000664 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000665 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000666 xmlFree(elem);
667}
668
669/**
670 * xmlSchemaFreeFacet:
671 * @facet: a schema facet structure
672 *
673 * Deallocate a Schema Facet structure.
674 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000675void
Daniel Veillard4255d502002-04-16 15:50:10 +0000676xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
677{
678 if (facet == NULL)
679 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000680 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000681 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000682 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000683 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000684 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000685 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000686 xmlFree(facet);
687}
688
689/**
690 * xmlSchemaFreeType:
691 * @type: a schema type structure
692 *
693 * Deallocate a Schema Type structure.
694 */
695void
696xmlSchemaFreeType(xmlSchemaTypePtr type)
697{
698 if (type == NULL)
699 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000700 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000701 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000702 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000703 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000704
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000705 facet = type->facets;
706 while (facet != NULL) {
707 next = facet->next;
708 xmlSchemaFreeFacet(facet);
709 facet = next;
710 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000711 }
Daniel Veillard3646d642004-06-02 19:19:14 +0000712 if (type->type != XML_SCHEMA_TYPE_BASIC) {
713 if (type->attributeUses != NULL)
714 xmlSchemaFreeAttributeUseList(type->attributeUses);
715 if ((type->attributeWildcard != NULL) &&
716 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
717 ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
718 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)))) {
719 xmlSchemaFreeWildcard(type->attributeWildcard);
720 }
721 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000722 xmlFree(type);
723}
724
725/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000726 * xmlSchemaFreeTypeList:
727 * @type: a schema type structure
728 *
729 * Deallocate a Schema Type structure.
730 */
731static void
732xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
733{
734 xmlSchemaTypePtr next;
735
736 while (type != NULL) {
737 next = type->redef;
738 xmlSchemaFreeType(type);
739 type = next;
740 }
741}
742
743/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000744 * xmlSchemaFree:
745 * @schema: a schema structure
746 *
747 * Deallocate a Schema structure.
748 */
749void
750xmlSchemaFree(xmlSchemaPtr schema)
751{
752 if (schema == NULL)
753 return;
754
Daniel Veillard4255d502002-04-16 15:50:10 +0000755 if (schema->notaDecl != NULL)
756 xmlHashFree(schema->notaDecl,
757 (xmlHashDeallocator) xmlSchemaFreeNotation);
758 if (schema->attrDecl != NULL)
759 xmlHashFree(schema->attrDecl,
760 (xmlHashDeallocator) xmlSchemaFreeAttribute);
761 if (schema->attrgrpDecl != NULL)
762 xmlHashFree(schema->attrgrpDecl,
763 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
764 if (schema->elemDecl != NULL)
765 xmlHashFree(schema->elemDecl,
766 (xmlHashDeallocator) xmlSchemaFreeElement);
767 if (schema->typeDecl != NULL)
768 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000769 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000770 if (schema->groupDecl != NULL)
771 xmlHashFree(schema->groupDecl,
772 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +0000773 if (schema->schemasImports != NULL)
774 xmlHashFree(schema->schemasImports,
775 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000776 if (schema->includes != NULL) {
777 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
778 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000779 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000780 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +0000781 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000782 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000783 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000784
785 xmlFree(schema);
786}
787
788/************************************************************************
789 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000790 * Debug functions *
791 * *
792 ************************************************************************/
793
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000794#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000795
Daniel Veillard4255d502002-04-16 15:50:10 +0000796/**
797 * xmlSchemaElementDump:
798 * @elem: an element
799 * @output: the file output
800 *
801 * Dump the element
802 */
803static void
804xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000805 const xmlChar * name ATTRIBUTE_UNUSED,
806 const xmlChar * context ATTRIBUTE_UNUSED,
807 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000808{
809 if (elem == NULL)
810 return;
811
812 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +0000813 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
814 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000815 fprintf(output, ": %s ", elem->name);
816 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000817 fprintf(output, "namespace '%s' ", namespace);
818
Daniel Veillard4255d502002-04-16 15:50:10 +0000819 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000820 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000821 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000822 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000823 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000824 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000825 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000826 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000827 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000828 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000829 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000830 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000831 fprintf(output, "\n");
832 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000833 fprintf(output, " ");
834 if (elem->minOccurs != 1)
835 fprintf(output, "min: %d ", elem->minOccurs);
836 if (elem->maxOccurs >= UNBOUNDED)
837 fprintf(output, "max: unbounded\n");
838 else if (elem->maxOccurs != 1)
839 fprintf(output, "max: %d\n", elem->maxOccurs);
840 else
841 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000842 }
843 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000844 fprintf(output, " type: %s", elem->namedType);
845 if (elem->namedTypeNs != NULL)
846 fprintf(output, " ns %s\n", elem->namedTypeNs);
847 else
848 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000849 }
850 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000851 fprintf(output, " substitutionGroup: %s", elem->substGroup);
852 if (elem->substGroupNs != NULL)
853 fprintf(output, " ns %s\n", elem->substGroupNs);
854 else
855 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000856 }
857 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000858 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000859}
860
861/**
862 * xmlSchemaAnnotDump:
863 * @output: the file output
864 * @annot: a annotation
865 *
866 * Dump the annotation
867 */
868static void
869xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
870{
871 xmlChar *content;
872
873 if (annot == NULL)
874 return;
875
876 content = xmlNodeGetContent(annot->content);
877 if (content != NULL) {
878 fprintf(output, " Annot: %s\n", content);
879 xmlFree(content);
880 } else
881 fprintf(output, " Annot: empty\n");
882}
883
884/**
885 * xmlSchemaTypeDump:
886 * @output: the file output
887 * @type: a type structure
888 *
889 * Dump a SchemaType structure
890 */
891static void
892xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
893{
894 if (type == NULL) {
895 fprintf(output, "Type: NULL\n");
896 return;
897 }
898 fprintf(output, "Type: ");
899 if (type->name != NULL)
900 fprintf(output, "%s, ", type->name);
901 else
902 fprintf(output, "no name");
903 switch (type->type) {
904 case XML_SCHEMA_TYPE_BASIC:
905 fprintf(output, "basic ");
906 break;
907 case XML_SCHEMA_TYPE_SIMPLE:
908 fprintf(output, "simple ");
909 break;
910 case XML_SCHEMA_TYPE_COMPLEX:
911 fprintf(output, "complex ");
912 break;
913 case XML_SCHEMA_TYPE_SEQUENCE:
914 fprintf(output, "sequence ");
915 break;
916 case XML_SCHEMA_TYPE_CHOICE:
917 fprintf(output, "choice ");
918 break;
919 case XML_SCHEMA_TYPE_ALL:
920 fprintf(output, "all ");
921 break;
922 case XML_SCHEMA_TYPE_UR:
923 fprintf(output, "ur ");
924 break;
925 case XML_SCHEMA_TYPE_RESTRICTION:
926 fprintf(output, "restriction ");
927 break;
928 case XML_SCHEMA_TYPE_EXTENSION:
929 fprintf(output, "extension ");
930 break;
931 default:
932 fprintf(output, "unknowntype%d ", type->type);
933 break;
934 }
935 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000936 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000937 }
938 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000939 case XML_SCHEMA_CONTENT_UNKNOWN:
940 fprintf(output, "unknown ");
941 break;
942 case XML_SCHEMA_CONTENT_EMPTY:
943 fprintf(output, "empty ");
944 break;
945 case XML_SCHEMA_CONTENT_ELEMENTS:
946 fprintf(output, "element ");
947 break;
948 case XML_SCHEMA_CONTENT_MIXED:
949 fprintf(output, "mixed ");
950 break;
951 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
952 fprintf(output, "mixed_or_elems ");
953 break;
954 case XML_SCHEMA_CONTENT_BASIC:
955 fprintf(output, "basic ");
956 break;
957 case XML_SCHEMA_CONTENT_SIMPLE:
958 fprintf(output, "simple ");
959 break;
960 case XML_SCHEMA_CONTENT_ANY:
961 fprintf(output, "any ");
962 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000963 }
964 fprintf(output, "\n");
965 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000966 fprintf(output, " ");
967 if (type->minOccurs != 1)
968 fprintf(output, "min: %d ", type->minOccurs);
969 if (type->maxOccurs >= UNBOUNDED)
970 fprintf(output, "max: unbounded\n");
971 else if (type->maxOccurs != 1)
972 fprintf(output, "max: %d\n", type->maxOccurs);
973 else
974 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000975 }
976 if (type->annot != NULL)
977 xmlSchemaAnnotDump(output, type->annot);
978 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000979 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000980
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000981 fprintf(output, " subtypes: ");
982 while (sub != NULL) {
983 fprintf(output, "%s ", sub->name);
984 sub = sub->next;
985 }
986 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000987 }
988
989}
990
991/**
992 * xmlSchemaDump:
993 * @output: the file output
994 * @schema: a schema structure
995 *
996 * Dump a Schema structure.
997 */
998void
999xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
1000{
1001 if (schema == NULL) {
1002 fprintf(output, "Schemas: NULL\n");
1003 return;
1004 }
1005 fprintf(output, "Schemas: ");
1006 if (schema->name != NULL)
1007 fprintf(output, "%s, ", schema->name);
1008 else
1009 fprintf(output, "no name, ");
1010 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001011 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001012 else
1013 fprintf(output, "no target namespace");
1014 fprintf(output, "\n");
1015 if (schema->annot != NULL)
1016 xmlSchemaAnnotDump(output, schema->annot);
1017
1018 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
1019 output);
1020 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001021 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00001022}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001023#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00001024
1025/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001026 * *
1027 * Utilities *
1028 * *
1029 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001030
1031/**
1032 * xmlSchemaGetProp:
1033 * @ctxt: the parser context
1034 * @node: the node
1035 * @name: the property name
1036 *
1037 * Read a attribute value and internalize the string
1038 *
1039 * Returns the string or NULL if not present.
1040 */
1041static const xmlChar *
1042xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1043 const char *name)
1044{
1045 xmlChar *val;
1046 const xmlChar *ret;
1047
1048 val = xmlGetProp(node, BAD_CAST name);
1049 if (val == NULL)
1050 return(NULL);
1051 ret = xmlDictLookup(ctxt->dict, val, -1);
1052 xmlFree(val);
1053 return(ret);
1054}
1055
William M. Brack29aa7722004-05-12 00:27:56 +00001056#if 0
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001057/**
1058 * xmlSchemaGetNamespace:
1059 * @ctxt: the parser context
1060 * @schema: the schemas containing the declaration
1061 * @node: the node
1062 * @qname: the QName to analyze
1063 *
1064 * Find the namespace name for the given declaration.
1065 *
1066 * Returns the local name for that declaration, as well as the namespace name
William M. Bracke7091952004-05-11 15:09:58 +00001067 * NOTE: This function is no longer used (Buchcik, May '04)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001068 */
1069static const xmlChar *
1070xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1071 xmlNodePtr node, const xmlChar *qname,
1072 const xmlChar **namespace) {
1073 int len;
1074 const xmlChar *name, *prefix, *def = NULL;
1075 xmlNsPtr ns;
1076
1077 *namespace = NULL;
1078
William M. Bracke7091952004-05-11 15:09:58 +00001079 /* TODO: The following seems to be not correct here:
1080 * 1. The name of a declaration is a NCName, not a QName.
1081 * 2. The attribute "targetNamespace" is allowed for the
1082 * <schema> Element Information Item only.
1083 * 3. One cannot evaluate the target namespace, by the type
1084 * of declaration, since it is dependant on the xxxFormDefault
1085 * of <schema> and the form attribute of an <element> or <attribute>.
1086 */
1087
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001088 if (xmlStrEqual(node->name, BAD_CAST "element") ||
1089 xmlStrEqual(node->name, BAD_CAST "attribute") ||
1090 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
1091 xmlStrEqual(node->name, BAD_CAST "complexType")) {
1092 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
1093 }
1094
William M. Bracke7091952004-05-11 15:09:58 +00001095
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001096 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
1097 name = xmlSplitQName3(qname, &len);
1098 if (name == NULL) {
1099 if (def == NULL) {
1100 if (xmlStrEqual(node->name, BAD_CAST "element")) {
1101 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
1102 *namespace = schema->targetNamespace;
1103 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
1104 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
1105 *namespace = schema->targetNamespace;
1106 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
1107 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
1108 *namespace = schema->targetNamespace;
1109 }
1110 } else {
1111 *namespace = def;
1112 }
1113 return(qname);
1114 }
William M. Bracke7091952004-05-11 15:09:58 +00001115
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001116 name = xmlDictLookup(ctxt->dict, name, -1);
1117 prefix = xmlDictLookup(ctxt->dict, qname, len);
1118 if (def != NULL) {
1119 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
1120 "%s: presence of both prefix %s and targetNamespace\n",
1121 node->name, prefix);
1122 }
1123 ns = xmlSearchNs(node->doc, node, prefix);
1124 if (ns == NULL) {
1125 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1126 "%s: the QName prefix %s is undefined\n",
1127 node->name, prefix);
1128 return(name);
1129 }
1130 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1131 return(name);
1132}
William M. Brack29aa7722004-05-12 00:27:56 +00001133#endif
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001134
1135/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00001136 * *
1137 * Parsing functions *
1138 * *
1139 ************************************************************************/
1140
1141/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001142 * xmlSchemaGetElem:
1143 * @schema: the schemas context
1144 * @name: the element name
1145 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001146 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001147 *
1148 * Lookup a an element in the schemas or the accessible schemas
1149 *
1150 * Returns the element definition or NULL if not found.
1151 */
1152static xmlSchemaElementPtr
1153xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001154 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001155{
1156 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001157 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001158
1159 if ((name == NULL) || (schema == NULL))
1160 return (NULL);
1161
Daniel Veillard3646d642004-06-02 19:19:14 +00001162
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001163 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001164 if ((ret != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00001165 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_GLOBAL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001166 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00001167 } else
1168 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00001169 /*
1170 * This one was removed, since top level element declarations have
1171 * the target namespace specified in targetNamespace of the <schema>
1172 * information element, even if elementFormDefault is "unqualified".
1173 */
1174
1175 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001176 if (xmlStrEqual(namespace, schema->targetNamespace))
1177 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1178 else
1179 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001180 if ((ret != NULL) &&
1181 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001182 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001183 }
William M. Bracke7091952004-05-11 15:09:58 +00001184 */
Daniel Veillard3646d642004-06-02 19:19:14 +00001185
1186 /* if (level > 0) */
1187 if (namespace == NULL)
1188 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1189 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001190 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001191 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00001192 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00001193 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
1194 return (ret);
1195 } else
1196 ret = NULL;
1197 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001198#ifdef DEBUG
1199 if (ret == NULL) {
1200 if (namespace == NULL)
1201 fprintf(stderr, "Unable to lookup type %s", name);
1202 else
1203 fprintf(stderr, "Unable to lookup type %s:%s", name,
1204 namespace);
1205 }
1206#endif
1207 return (ret);
1208}
1209
1210/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001211 * xmlSchemaGetType:
1212 * @schema: the schemas context
1213 * @name: the type name
1214 * @ns: the type namespace
1215 *
1216 * Lookup a type in the schemas or the predefined types
1217 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001218 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001219 */
1220static xmlSchemaTypePtr
1221xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001222 const xmlChar * namespace)
1223{
Daniel Veillard4255d502002-04-16 15:50:10 +00001224 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001225 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001226
1227 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001228 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001229 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001230 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001231 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001232 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001233 }
1234 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001235 if (ret != NULL)
1236 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00001237 if (namespace == NULL)
1238 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1239 else
Daniel Veillard1d913862003-11-21 00:28:39 +00001240 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001241 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00001242 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001243 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1244 return (ret);
1245 } else
1246 ret = NULL;
1247 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001248#ifdef DEBUG
1249 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001250 if (namespace == NULL)
1251 fprintf(stderr, "Unable to lookup type %s", name);
1252 else
1253 fprintf(stderr, "Unable to lookup type %s:%s", name,
1254 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001255 }
1256#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001257 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001258}
1259
Daniel Veillard3646d642004-06-02 19:19:14 +00001260/**
1261 * xmlSchemaGetAttribute:
1262 * @schema: the context of the schema
1263 * @name: the name of the attribute
1264 * @ns: the target namespace of the attribute
1265 *
1266 * Lookup a an attribute in the schema or imported schemas
1267 *
1268 * Returns the attribute declaration or NULL if not found.
1269 */
1270static xmlSchemaAttributePtr
1271xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
1272 const xmlChar * namespace)
1273{
1274 xmlSchemaAttributePtr ret;
1275 xmlSchemaImportPtr import = NULL;
1276
1277 if ((name == NULL) || (schema == NULL))
1278 return (NULL);
1279
1280
1281 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
1282 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
1283 return (ret);
1284 else
1285 ret = NULL;
1286 if (namespace == NULL)
1287 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1288 else
1289 import = xmlHashLookup(schema->schemasImports, namespace);
1290 if (import != NULL) {
1291 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
1292 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
1293 return (ret);
1294 } else
1295 ret = NULL;
1296 }
1297#ifdef DEBUG
1298 if (ret == NULL) {
1299 if (namespace == NULL)
1300 fprintf(stderr, "Unable to lookup attribute %s", name);
1301 else
1302 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
1303 namespace);
1304 }
1305#endif
1306 return (ret);
1307}
1308
1309/**
1310 * xmlSchemaGetAttributeGroup:
1311 * @schema: the context of the schema
1312 * @name: the name of the attribute group
1313 * @ns: the target namespace of the attribute group
1314 *
1315 * Lookup a an attribute group in the schema or imported schemas
1316 *
1317 * Returns the attribute group definition or NULL if not found.
1318 */
1319static xmlSchemaAttributeGroupPtr
1320xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
1321 const xmlChar * namespace)
1322{
1323 xmlSchemaAttributeGroupPtr ret;
1324 xmlSchemaImportPtr import = NULL;
1325
1326 if ((name == NULL) || (schema == NULL))
1327 return (NULL);
1328
1329
1330 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
1331 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
1332 return (ret);
1333 else
1334 ret = NULL;
1335 if (namespace == NULL)
1336 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1337 else
1338 import = xmlHashLookup(schema->schemasImports, namespace);
1339 if (import != NULL) {
1340 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
1341 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
1342 return (ret);
1343 else
1344 ret = NULL;
1345 }
1346#ifdef DEBUG
1347 if (ret == NULL) {
1348 if (namespace == NULL)
1349 fprintf(stderr, "Unable to lookup attribute group %s", name);
1350 else
1351 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
1352 namespace);
1353 }
1354#endif
1355 return (ret);
1356}
1357
1358/**
1359 * xmlSchemaGetGroup:
1360 * @schema: the context of the schema
1361 * @name: the name of the group
1362 * @ns: the target namespace of the group
1363 *
1364 * Lookup a group in the schema or imported schemas
1365 *
1366 * Returns the group definition or NULL if not found.
1367 */
1368static xmlSchemaTypePtr
1369xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
1370 const xmlChar * namespace)
1371{
1372 xmlSchemaTypePtr ret;
1373 xmlSchemaImportPtr import = NULL;
1374
1375 if ((name == NULL) || (schema == NULL))
1376 return (NULL);
1377
1378
1379 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
1380 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
1381 return (ret);
1382 else
1383 ret = NULL;
1384 if (namespace == NULL)
1385 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1386 else
1387 import = xmlHashLookup(schema->schemasImports, namespace);
1388 if (import != NULL) {
1389 ret = xmlSchemaGetGroup(import->schema, name, namespace);
1390 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
1391 return (ret);
1392 else
1393 ret = NULL;
1394 }
1395#ifdef DEBUG
1396 if (ret == NULL) {
1397 if (namespace == NULL)
1398 fprintf(stderr, "Unable to lookup group %s", name);
1399 else
1400 fprintf(stderr, "Unable to lookup group %s:%s", name,
1401 namespace);
1402 }
1403#endif
1404 return (ret);
1405}
1406
Daniel Veillard4255d502002-04-16 15:50:10 +00001407/************************************************************************
1408 * *
1409 * Parsing functions *
1410 * *
1411 ************************************************************************/
1412
1413#define IS_BLANK_NODE(n) \
1414 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1415
1416/**
1417 * xmlSchemaIsBlank:
1418 * @str: a string
1419 *
1420 * Check if a string is ignorable
1421 *
1422 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1423 */
1424static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001425xmlSchemaIsBlank(xmlChar * str)
1426{
Daniel Veillard4255d502002-04-16 15:50:10 +00001427 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001428 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001429 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001430 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001431 return (0);
1432 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001433 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001434 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001435}
1436
1437/**
1438 * xmlSchemaAddNotation:
1439 * @ctxt: a schema validation context
1440 * @schema: the schema being built
1441 * @name: the item name
1442 *
1443 * Add an XML schema Attrribute declaration
1444 * *WARNING* this interface is highly subject to change
1445 *
1446 * Returns the new struture or NULL in case of error
1447 */
1448static xmlSchemaNotationPtr
1449xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001450 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001451{
1452 xmlSchemaNotationPtr ret = NULL;
1453 int val;
1454
1455 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1456 return (NULL);
1457
1458 if (schema->notaDecl == NULL)
1459 schema->notaDecl = xmlHashCreate(10);
1460 if (schema->notaDecl == NULL)
1461 return (NULL);
1462
1463 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1464 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001465 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001466 return (NULL);
1467 }
1468 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001469 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001470 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1471 ret);
1472 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001473 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1474 XML_SCHEMAP_REDEFINED_NOTATION,
1475 "Notation %s already defined\n",
1476 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001477 xmlFree(ret);
1478 return (NULL);
1479 }
1480 return (ret);
1481}
1482
1483
1484/**
1485 * xmlSchemaAddAttribute:
1486 * @ctxt: a schema validation context
1487 * @schema: the schema being built
1488 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001489 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001490 *
1491 * Add an XML schema Attrribute declaration
1492 * *WARNING* this interface is highly subject to change
1493 *
1494 * Returns the new struture or NULL in case of error
1495 */
1496static xmlSchemaAttributePtr
1497xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001498 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001499{
1500 xmlSchemaAttributePtr ret = NULL;
1501 int val;
1502
1503 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1504 return (NULL);
1505
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001506#ifdef DEBUG
1507 fprintf(stderr, "Adding attribute %s\n", name);
1508 if (namespace != NULL)
1509 fprintf(stderr, " target namespace %s\n", namespace);
1510#endif
1511
Daniel Veillard4255d502002-04-16 15:50:10 +00001512 if (schema->attrDecl == NULL)
1513 schema->attrDecl = xmlHashCreate(10);
1514 if (schema->attrDecl == NULL)
1515 return (NULL);
1516
1517 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1518 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001519 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001520 return (NULL);
1521 }
1522 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001523 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1524 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001525 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001526 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001527 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001528 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1529 XML_SCHEMAP_REDEFINED_ATTR,
1530 "Attribute %s already defined\n",
1531 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001532 xmlFree(ret);
1533 return (NULL);
1534 }
1535 return (ret);
1536}
1537
1538/**
1539 * xmlSchemaAddAttributeGroup:
1540 * @ctxt: a schema validation context
1541 * @schema: the schema being built
1542 * @name: the item name
1543 *
1544 * Add an XML schema Attrribute Group declaration
1545 *
1546 * Returns the new struture or NULL in case of error
1547 */
1548static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001549xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1550 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001551{
1552 xmlSchemaAttributeGroupPtr ret = NULL;
1553 int val;
1554
1555 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1556 return (NULL);
1557
1558 if (schema->attrgrpDecl == NULL)
1559 schema->attrgrpDecl = xmlHashCreate(10);
1560 if (schema->attrgrpDecl == NULL)
1561 return (NULL);
1562
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001563 ret =
1564 (xmlSchemaAttributeGroupPtr)
1565 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001566 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001567 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001568 return (NULL);
1569 }
1570 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001571 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001572 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001573 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001574 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001575 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1576 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1577 "Attribute group %s already defined\n",
1578 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001579 xmlFree(ret);
1580 return (NULL);
1581 }
1582 return (ret);
1583}
1584
1585/**
1586 * xmlSchemaAddElement:
1587 * @ctxt: a schema validation context
1588 * @schema: the schema being built
1589 * @name: the type name
1590 * @namespace: the type namespace
1591 *
1592 * Add an XML schema Element declaration
1593 * *WARNING* this interface is highly subject to change
1594 *
1595 * Returns the new struture or NULL in case of error
1596 */
1597static xmlSchemaElementPtr
1598xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1599 const xmlChar * name, const xmlChar * namespace)
1600{
1601 xmlSchemaElementPtr ret = NULL;
1602 int val;
1603
1604 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1605 return (NULL);
1606
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001607#ifdef DEBUG
1608 fprintf(stderr, "Adding element %s\n", name);
1609 if (namespace != NULL)
1610 fprintf(stderr, " target namespace %s\n", namespace);
1611#endif
1612
Daniel Veillard4255d502002-04-16 15:50:10 +00001613 if (schema->elemDecl == NULL)
1614 schema->elemDecl = xmlHashCreate(10);
1615 if (schema->elemDecl == NULL)
1616 return (NULL);
1617
1618 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1619 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001620 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001621 return (NULL);
1622 }
1623 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001624 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1625 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001626 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001627 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001628 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001629 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001630
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001631 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001632 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1633 namespace, ret);
1634 if (val != 0) {
1635 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1636 XML_SCHEMAP_REDEFINED_ELEMENT,
1637 "Element %s already defined\n",
1638 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001639 xmlFree(ret);
1640 return (NULL);
1641 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001642 }
1643 return (ret);
1644}
1645
1646/**
1647 * xmlSchemaAddType:
1648 * @ctxt: a schema validation context
1649 * @schema: the schema being built
1650 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001651 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001652 *
1653 * Add an XML schema Simple Type definition
1654 * *WARNING* this interface is highly subject to change
1655 *
1656 * Returns the new struture or NULL in case of error
1657 */
1658static xmlSchemaTypePtr
1659xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001660 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001661{
1662 xmlSchemaTypePtr ret = NULL;
1663 int val;
1664
1665 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1666 return (NULL);
1667
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001668#ifdef DEBUG
1669 fprintf(stderr, "Adding type %s\n", name);
1670 if (namespace != NULL)
1671 fprintf(stderr, " target namespace %s\n", namespace);
1672#endif
1673
Daniel Veillard4255d502002-04-16 15:50:10 +00001674 if (schema->typeDecl == NULL)
1675 schema->typeDecl = xmlHashCreate(10);
1676 if (schema->typeDecl == NULL)
1677 return (NULL);
1678
1679 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1680 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001681 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001682 return (NULL);
1683 }
1684 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001685 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001686 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001687 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001688 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001689 if (ctxt->includes == 0) {
1690 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1691 XML_SCHEMAP_REDEFINED_TYPE,
1692 "Type %s already defined\n",
1693 name, NULL);
1694 xmlFree(ret);
1695 return (NULL);
1696 } else {
1697 xmlSchemaTypePtr prev;
1698
1699 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1700 if (prev == NULL) {
1701 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1702 XML_ERR_INTERNAL_ERROR,
1703 "Internal error on type %s definition\n",
1704 name, NULL);
1705 xmlFree(ret);
1706 return (NULL);
1707 }
1708 ret->redef = prev->redef;
1709 prev->redef = ret;
1710 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001711 }
1712 ret->minOccurs = 1;
1713 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00001714 ret->attributeUses = NULL;
1715 ret->attributeWildcard = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001716
1717 return (ret);
1718}
1719
1720/**
1721 * xmlSchemaAddGroup:
1722 * @ctxt: a schema validation context
1723 * @schema: the schema being built
1724 * @name: the group name
1725 *
1726 * Add an XML schema Group definition
1727 *
1728 * Returns the new struture or NULL in case of error
1729 */
1730static xmlSchemaTypePtr
1731xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001732 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001733{
1734 xmlSchemaTypePtr ret = NULL;
1735 int val;
1736
1737 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1738 return (NULL);
1739
1740 if (schema->groupDecl == NULL)
1741 schema->groupDecl = xmlHashCreate(10);
1742 if (schema->groupDecl == NULL)
1743 return (NULL);
1744
1745 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1746 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001747 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001748 return (NULL);
1749 }
1750 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001751 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001752 val =
1753 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1754 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001755 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001756 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1757 XML_SCHEMAP_REDEFINED_GROUP,
1758 "Group %s already defined\n",
1759 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001760 xmlFree(ret);
1761 return (NULL);
1762 }
1763 ret->minOccurs = 1;
1764 ret->maxOccurs = 1;
1765
1766 return (ret);
1767}
1768
Daniel Veillard3646d642004-06-02 19:19:14 +00001769/**
1770 * xmlSchemaNewWildcardNs:
1771 * @ctxt: a schema validation context
1772 *
1773 * Creates a new wildcard namespace constraint.
1774 *
1775 * Returns the new struture or NULL in case of error
1776 */
1777static xmlSchemaWildcardNsPtr
1778xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
1779{
1780 xmlSchemaWildcardNsPtr ret;
1781
1782 ret = (xmlSchemaWildcardNsPtr)
1783 xmlMalloc(sizeof(xmlSchemaWildcardNs));
1784 if (ret == NULL) {
1785 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
1786 return (NULL);
1787 }
1788 ret->value = NULL;
1789 ret->next = NULL;
1790 return (ret);
1791}
1792
1793/**
1794 * xmlSchemaAddWildcard:
1795 * @ctxt: a schema validation context
1796 * @schema: the schema being built
1797 * @name: the group name
1798 *
1799 * Add an XML schema Group definition
1800 *
1801 * Returns the new struture or NULL in case of error
1802 */
1803static xmlSchemaWildcardPtr
1804xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
1805{
1806 xmlSchemaWildcardPtr ret = NULL;
1807
1808 if (ctxt == NULL)
1809 return (NULL);
1810
1811 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
1812 if (ret == NULL) {
1813 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
1814 return (NULL);
1815 }
1816 memset(ret, 0, sizeof(xmlSchemaWildcard));
1817 ret->minOccurs = 1;
1818 ret->maxOccurs = 1;
1819
1820 return (ret);
1821}
1822
Daniel Veillard4255d502002-04-16 15:50:10 +00001823/************************************************************************
1824 * *
1825 * Utilities for parsing *
1826 * *
1827 ************************************************************************/
1828
1829/**
1830 * xmlGetQNameProp:
1831 * @ctxt: a schema validation context
1832 * @node: a subtree containing XML Schema informations
1833 * @name: the attribute name
1834 * @namespace: the result namespace if any
1835 *
1836 * Extract a QName Attribute value
1837 *
1838 * Returns the NCName or NULL if not found, and also update @namespace
1839 * with the namespace URI
1840 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001841static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001842xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001843 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001844{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001845 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001846 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001847 const xmlChar *ret, *prefix;
1848 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001849
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001850 *namespace = NULL;
1851 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001852 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001853 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001854
Daniel Veillardba0153a2004-04-01 10:42:31 +00001855 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00001856 ns = xmlSearchNs(node->doc, node, 0);
1857 if (ns) {
1858 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1859 return (val);
1860 }
1861 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001862 ret = xmlSplitQName3(val, &len);
1863 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001864 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001865 }
1866 ret = xmlDictLookup(ctxt->dict, ret, -1);
1867 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001868
1869 ns = xmlSearchNs(node->doc, node, prefix);
1870 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001871 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1872 "Attribute %s: the QName prefix %s is undefined\n",
1873 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001874 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001875 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001876 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001877 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001878}
1879
1880/**
1881 * xmlGetMaxOccurs:
1882 * @ctxt: a schema validation context
1883 * @node: a subtree containing XML Schema informations
1884 *
1885 * Get the maxOccurs property
1886 *
1887 * Returns the default if not found, or the value
1888 */
1889static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001890xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1891{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001892 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001893 int ret = 0;
1894
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001895 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001896 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001897 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001898
1899 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001900 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001901 }
1902
1903 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001904 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001905 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001906 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001907 ret = ret * 10 + (*cur - '0');
1908 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001909 }
William M. Brack76e95df2003-10-18 16:20:14 +00001910 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001911 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001912 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001913 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1914 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001915 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001916 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001917 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001918}
1919
1920/**
1921 * xmlGetMinOccurs:
1922 * @ctxt: a schema validation context
1923 * @node: a subtree containing XML Schema informations
1924 *
1925 * Get the minOccurs property
1926 *
1927 * Returns the default if not found, or the value
1928 */
1929static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001930xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1931{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001932 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001933 int ret = 0;
1934
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001935 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001936 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001937 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001938
1939 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001940 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001941 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001942 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001943 ret = ret * 10 + (*cur - '0');
1944 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001945 }
William M. Brack76e95df2003-10-18 16:20:14 +00001946 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001947 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001948 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001949 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1950 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001951 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001952 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001953 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001954}
1955
1956/**
1957 * xmlGetBooleanProp:
1958 * @ctxt: a schema validation context
1959 * @node: a subtree containing XML Schema informations
1960 * @name: the attribute name
1961 * @def: the default value
1962 *
1963 * Get is a bolean property is set
1964 *
1965 * Returns the default if not found, 0 if found to be false,
1966 * 1 if found to be true
1967 */
1968static int
1969xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001970 const char *name, int def)
1971{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001972 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001973
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001974 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001975 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001976 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001977
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001978 if (xmlStrEqual(val, BAD_CAST "true"))
1979 def = 1;
1980 else if (xmlStrEqual(val, BAD_CAST "false"))
1981 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001982 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001983 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1984 "Attribute %s: the value %s is not boolean\n",
1985 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001986 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001987 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001988}
1989
1990/************************************************************************
1991 * *
1992 * Shema extraction from an Infoset *
1993 * *
1994 ************************************************************************/
1995static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1996 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00001997 xmlNodePtr node,
1998 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001999static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
2000 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00002001 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00002002 xmlNodePtr node,
2003 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002004static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
2005 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00002006 xmlSchemaPtr schema,
2007 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002008 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00002009static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
2010 xmlSchemaPtr schema,
2011 xmlNodePtr node);
2012static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
2013 xmlSchemaPtr schema,
2014 xmlNodePtr node);
2015static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
2016 ctxt,
2017 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002018 xmlNodePtr node,
2019 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002020static xmlSchemaAttributeGroupPtr
2021xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00002022 xmlSchemaPtr schema, xmlNodePtr node,
2023 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002024static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
2025 xmlSchemaPtr schema,
2026 xmlNodePtr node);
2027static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
2028 xmlSchemaPtr schema,
2029 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00002030static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002031xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
2032 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002033
2034/**
2035 * xmlSchemaParseAttrDecls:
2036 * @ctxt: a schema validation context
2037 * @schema: the schema being built
2038 * @node: a subtree containing XML Schema informations
2039 * @type: the hosting type
2040 *
2041 * parse a XML schema attrDecls declaration corresponding to
2042 * <!ENTITY % attrDecls
2043 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
2044 */
2045static xmlNodePtr
2046xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2047 xmlNodePtr child, xmlSchemaTypePtr type)
2048{
2049 xmlSchemaAttributePtr lastattr, attr;
2050
2051 lastattr = NULL;
2052 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002053 (IS_SCHEMA(child, "attributeGroup"))) {
2054 attr = NULL;
2055 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00002056 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002057 } else if (IS_SCHEMA(child, "attributeGroup")) {
2058 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00002059 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002060 }
2061 if (attr != NULL) {
2062 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002063 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
2064 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
2065 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002066 type->attributes = attr;
2067 lastattr = attr;
2068 } else {
2069 lastattr->next = attr;
2070 lastattr = attr;
2071 }
2072 }
2073 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002074 }
2075 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002076 xmlSchemaWildcardPtr wildcard;
2077
2078 wildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
2079 if (wildcard != NULL) {
2080 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
2081 ((xmlSchemaAttributeGroupPtr) type)->attributeWildcard = wildcard;
2082 else
2083 type->attributeWildcard = wildcard;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002084 }
2085 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002086 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002087 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002088}
2089
2090/**
2091 * xmlSchemaParseAnnotation:
2092 * @ctxt: a schema validation context
2093 * @schema: the schema being built
2094 * @node: a subtree containing XML Schema informations
2095 *
2096 * parse a XML schema Attrribute declaration
2097 * *WARNING* this interface is highly subject to change
2098 *
William M. Bracke7091952004-05-11 15:09:58 +00002099 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002100 * 1 in case of success.
2101 */
2102static xmlSchemaAnnotPtr
2103xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2104 xmlNodePtr node)
2105{
2106 xmlSchemaAnnotPtr ret;
2107
2108 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2109 return (NULL);
2110 ret = xmlSchemaNewAnnot(ctxt, node);
2111
2112 return (ret);
2113}
2114
2115/**
2116 * xmlSchemaParseFacet:
2117 * @ctxt: a schema validation context
2118 * @schema: the schema being built
2119 * @node: a subtree containing XML Schema informations
2120 *
2121 * parse a XML schema Facet declaration
2122 * *WARNING* this interface is highly subject to change
2123 *
2124 * Returns the new type structure or NULL in case of error
2125 */
2126static xmlSchemaFacetPtr
2127xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002128 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002129{
2130 xmlSchemaFacetPtr facet;
2131 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002132 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00002133
2134 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2135 return (NULL);
2136
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002137 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002138 if (facet == NULL) {
2139 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
2140 return (NULL);
2141 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002142 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002143 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00002144 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002145 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
2146 "Facet %s has no value\n", node->name, NULL);
2147 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00002148 return (NULL);
2149 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002150 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002151 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002152 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002153 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002154 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002155 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002156 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002157 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002158 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002159 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002160 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002161 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002162 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002163 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002164 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002165 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002166 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002167 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002168 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002169 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002170 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002171 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
2172 } else if (IS_SCHEMA(node, "minLength")) {
2173 facet->type = XML_SCHEMA_FACET_MINLENGTH;
2174 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002175 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
2176 "Unknown facet type %s\n", node->name, NULL);
2177 xmlSchemaFreeFacet(facet);
2178 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002179 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002180 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002181 facet->value = value;
2182 child = node->children;
2183
2184 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002185 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2186 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002187 }
2188 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002189 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
2190 "Facet %s has unexpected child content\n",
2191 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002192 }
2193 return (facet);
2194}
2195
2196/**
2197 * xmlSchemaParseAny:
2198 * @ctxt: a schema validation context
2199 * @schema: the schema being built
2200 * @node: a subtree containing XML Schema informations
2201 *
2202 * parse a XML schema Any declaration
2203 * *WARNING* this interface is highly subject to change
2204 *
2205 * Returns the new type structure or NULL in case of error
2206 */
2207static xmlSchemaTypePtr
2208xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2209 xmlNodePtr node)
2210{
2211 xmlSchemaTypePtr type;
2212 xmlNodePtr child = NULL;
2213 xmlChar name[30];
2214
2215 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2216 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002217 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002218 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002219 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002220 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002221 type->node = node;
2222 type->type = XML_SCHEMA_TYPE_ANY;
2223 child = node->children;
2224 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2225 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2226
2227 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002228 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2229 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002230 }
2231 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002232 xmlSchemaPErr2(ctxt, node, child,
2233 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
2234 "Sequence %s has unexpected content\n", type->name,
2235 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002236 }
2237
2238 return (type);
2239}
2240
2241/**
2242 * xmlSchemaParseNotation:
2243 * @ctxt: a schema validation context
2244 * @schema: the schema being built
2245 * @node: a subtree containing XML Schema informations
2246 *
2247 * parse a XML schema Notation declaration
2248 *
2249 * Returns the new structure or NULL in case of error
2250 */
2251static xmlSchemaNotationPtr
2252xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002253 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002254{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002255 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002256 xmlSchemaNotationPtr ret;
2257 xmlNodePtr child = NULL;
2258
2259 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2260 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002261 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002262 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002263 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
2264 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002265 return (NULL);
2266 }
2267 ret = xmlSchemaAddNotation(ctxt, schema, name);
2268 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002269 return (NULL);
2270 }
2271 child = node->children;
2272 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002273 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2274 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002275 }
2276 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002277 xmlSchemaPErr2(ctxt, node, child,
2278 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
2279 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002280 }
2281
2282 return (ret);
2283}
2284
2285/**
2286 * xmlSchemaParseAnyAttribute:
2287 * @ctxt: a schema validation context
2288 * @schema: the schema being built
2289 * @node: a subtree containing XML Schema informations
2290 *
2291 * parse a XML schema AnyAttrribute declaration
2292 * *WARNING* this interface is highly subject to change
2293 *
2294 * Returns an attribute def structure or NULL
2295 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002296static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002297xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
2298 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002299{
Daniel Veillard3646d642004-06-02 19:19:14 +00002300 const xmlChar *processContents, *nsConstraint, *end, *cur, *dictMember;
2301 xmlChar *member;
2302 xmlSchemaWildcardPtr ret;
2303 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002304 xmlNodePtr child = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002305
2306 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2307 return (NULL);
2308
Daniel Veillard3646d642004-06-02 19:19:14 +00002309 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00002310 if (ret == NULL) {
2311 return (NULL);
2312 }
William M. Bracke7091952004-05-11 15:09:58 +00002313 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002314 ret->id = xmlSchemaGetProp(ctxt, node, "id");
2315 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002316 if ((processContents == NULL)
2317 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002318 ret->processContents = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002319 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002320 ret->processContents = XML_SCHEMAS_ANYATTR_SKIP;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002321 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002322 ret->processContents = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00002323 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00002324 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002325 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
William M. Bracke7091952004-05-11 15:09:58 +00002326 "anyAttribute has unexpected content "
2327 "for processContents: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002328 processContents, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00002329 ret->processContents = XML_SCHEMAS_ANYATTR_STRICT;
2330 }
2331 /*
2332 * Build the namespace constraints.
2333 */
2334 nsConstraint = xmlSchemaGetProp(ctxt, node, "namespace");
2335 if ((nsConstraint == NULL) || (xmlStrEqual(nsConstraint, "##any")))
2336 ret->any = 1;
2337 else if (xmlStrEqual(nsConstraint, "##other")) {
2338 ret->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
2339 if (ret->negNsSet == NULL) {
2340 xmlSchemaFreeWildcard(ret);
2341 return (NULL);
2342 }
2343 ret->negNsSet->value = schema->targetNamespace;
2344 } else {
2345 cur = nsConstraint;
2346 do {
2347 while (IS_BLANK_CH(*cur))
2348 cur++;
2349 end = cur;
2350 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
2351 end++;
2352 if (end == cur)
2353 break;
2354 member = xmlStrndup(cur, end - cur);
2355 if ((xmlStrEqual(member, "##other")) || (xmlStrEqual(member, "##any"))) {
2356 xmlSchemaPErr(ctxt, ret->node, XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
2357 "The namespace constraint of an anyAttribute "
2358 "is a set and must not contain \"%s\"\n",
2359 member, NULL);
2360 } else {
2361 /*
2362 * TODO: Validate the value (anyURI).
2363 */
2364 if (xmlStrEqual(member, "##targetNamespace")) {
2365 dictMember = schema->targetNamespace;
2366 } else if (xmlStrEqual(member, "##local")) {
2367 dictMember = NULL;
2368 } else
2369 dictMember = xmlDictLookup(ctxt->dict, member, -1);
2370 /*
2371 * Avoid dublicate namespaces.
2372 */
2373 tmp = ret->nsSet;
2374 while (tmp != NULL) {
2375 if (dictMember == tmp->value)
2376 break;
2377 tmp = tmp->next;
2378 }
2379 if (tmp == NULL) {
2380 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
2381 if (tmp == NULL) {
2382 xmlFree(member);
2383 xmlSchemaFreeWildcard(ret);
2384 return (NULL);
2385 }
2386 tmp->value = dictMember;
2387 tmp->next = NULL;
2388 if (ret->nsSet == NULL)
2389 ret->nsSet = tmp;
2390 else
2391 lastNs->next = tmp;
2392 lastNs = tmp;
2393 }
2394
2395 }
2396 xmlFree(member);
2397 cur = end;
2398 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00002399 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002400
2401 child = node->children;
2402 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002403 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2404 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002405 }
2406 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002407 xmlSchemaPErr2(ctxt, node, child,
2408 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
Daniel Veillard3646d642004-06-02 19:19:14 +00002409 "anyAttribute has unexpected content\n",
2410 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002411 }
2412
2413 return (ret);
2414}
2415
2416
2417/**
2418 * xmlSchemaParseAttribute:
2419 * @ctxt: a schema validation context
2420 * @schema: the schema being built
2421 * @node: a subtree containing XML Schema informations
2422 *
2423 * parse a XML schema Attrribute declaration
2424 * *WARNING* this interface is highly subject to change
2425 *
William M. Bracke7091952004-05-11 15:09:58 +00002426 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002427 */
2428static xmlSchemaAttributePtr
2429xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002430 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002431{
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002432 const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal;
Daniel Veillard4255d502002-04-16 15:50:10 +00002433 xmlSchemaAttributePtr ret;
2434 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002435 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002436 int hasRefType = 0;
William M. Bracke7091952004-05-11 15:09:58 +00002437
2438 /*
2439 * Note that the w3c spec assumes the schema to be validated with schema
2440 * for schemas beforehand.
2441 *
2442 * 3.2.3 Constraints on XML Representations of Attribute Declarations
2443 *
2444 * TODO: Complete implementation of:
2445 * 3.2.6 Schema Component Constraint: Attribute Declaration Properties
2446 * Correct
2447 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002448
2449 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2450 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002451
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002452 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002453 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002454 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002455 /* 3.2.3 : 3.1
2456 * One of ref or name must be present, but not both
2457 */
2458 if (ref == NULL) {
2459 xmlSchemaPErr(ctxt, node,
2460 XML_SCHEMAP_ATTR_NONAME_NOREF,
2461 "Attribute declaration has no \"name\" or \"ref\"\n",
2462 NULL, NULL);
2463 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002464 }
William M. Bracke7091952004-05-11 15:09:58 +00002465 hasRefType = 1;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002466 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2467 name = (const xmlChar *) buf;
2468 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002469 if (!topLevel) {
2470 /* 3.2.3 : 3.2
2471 * If ref is present, then all of <simpleType>,
2472 * form and type must be absent.
2473 */
2474 if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2475 xmlSchemaPErr(ctxt, node,
2476 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2477 "Attribute declaration %s has \"ref\", thus "
2478 "\"form\" must be absent\n", name, NULL);
2479 }
2480 if (xmlSchemaGetProp(ctxt, node, "type") != NULL) {
2481 xmlSchemaPErr(ctxt, node,
2482 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2483 "Attribute declaration %s has \"ref\", thus "
2484 "\"type\" must be absent\n", name, NULL);
2485 }
2486 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002487 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002488 const xmlChar *ns = NULL;
2489 /* 3.2.3 : 3.1
2490 * One of ref or name must be present, but not both
2491 */
2492 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2493 xmlSchemaPErr(ctxt, node,
2494 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
Daniel Veillard3646d642004-06-02 19:19:14 +00002495 "Attribute declaration \"%s\" has both, \"name\" and "
2496 "\"ref\"\n", name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002497 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002498
William M. Bracke7091952004-05-11 15:09:58 +00002499 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2500 /* Evaluate the target namespace */
2501 if (schema->targetNamespace != NULL) {
2502 if (topLevel) {
2503 ns = schema->targetNamespace;
2504 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2505 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2506 BAD_CAST "qualified")) {
2507 ns = schema->targetNamespace;
2508 }
2509 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2510 ns = schema->targetNamespace;
2511 }
2512 }
2513 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns);
Daniel Veillard3646d642004-06-02 19:19:14 +00002514 if (ret == NULL)
2515 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002516 /* 3.2.6 Schema Component Constraint: xmlns Not Allowed */
2517 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2518 xmlSchemaPErr(ctxt, node,
2519 XML_SCHEMAP_INVALID_ATTR_NAME,
2520 "The name of an attribute declaration must not match "
2521 "\"xmlns\".\n", NULL, NULL);
2522 }
2523
2524 /* 3.2.6 Schema Component Constraint: xsi: Not Allowed */
2525 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
2526 xmlSchemaPErr(ctxt, node,
2527 XML_SCHEMAP_INVALID_ATTR_NAME,
2528 "The target namespace of an attribute declaration, "
2529 "must not match \"http://www.w3.org/2001/"
2530 "XMLSchema-instance\"", NULL, NULL);
2531 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002532 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002533 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002534 return (NULL);
2535 }
William M. Bracke7091952004-05-11 15:09:58 +00002536 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Daniel Veillard3646d642004-06-02 19:19:14 +00002537 if (topLevel)
2538 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
William M. Bracke7091952004-05-11 15:09:58 +00002539
2540 /* Handle the "use" attribute. */
2541 attrVal = xmlSchemaGetProp(ctxt, node, "use");
2542 if (attrVal != NULL) {
2543 if (xmlStrEqual(attrVal, BAD_CAST "optional"))
2544 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2545 else if (xmlStrEqual(attrVal, BAD_CAST "prohibited"))
2546 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
2547 else if (xmlStrEqual(attrVal, BAD_CAST "required"))
2548 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
2549 else
2550 xmlSchemaPErr(ctxt, node,
2551 XML_SCHEMAP_INVALID_ATTR_USE,
2552 "Attribute declaration %s has an invalid "
2553 "value for \"use\"\n", name, NULL);
2554 } else
2555 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002556
William M. Bracke7091952004-05-11 15:09:58 +00002557
2558 if (xmlSchemaGetProp(ctxt, node, "default") != NULL) {
2559 /* 3.2.3 : 1
2560 * default and fixed must not both be present.
2561 */
2562 if (xmlSchemaGetProp(ctxt, node, "fixed") != NULL) {
2563 xmlSchemaPErr(ctxt, node,
2564 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2565 "Attribute declaration has both, \"default\" "
2566 "and \"fixed\"\n", NULL, NULL);
2567 }
2568 /* 3.2.3 : 2
2569 * If default and use are both present, use must have
2570 * the actual value optional.
2571 */
2572 if (ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) {
2573 xmlSchemaPErr(ctxt, node,
2574 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2575 "Attribute declaration has \"default\" but "
2576 "\"use\" is not \"optional\"\n", NULL, NULL);
2577 }
2578 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002579
Daniel Veillard4255d502002-04-16 15:50:10 +00002580 ret->ref = ref;
2581 ret->refNs = refNs;
William M. Bracke7091952004-05-11 15:09:58 +00002582 /*
2583 * The setting of XML_SCHEMAS_ATTR_NSDEFAULT is not needed anymore,
2584 * since the target namespace was already evaluated and took
2585 * attributeFormDefault into account.
2586 */
2587 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002588 if ((ret->targetNamespace != NULL) &&
2589 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2590 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2591 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
William M. Bracke7091952004-05-11 15:09:58 +00002592 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002593 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
William M. Bracke7091952004-05-11 15:09:58 +00002594 if (ret->typeName != NULL)
2595 hasRefType = 1;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002596 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002597 child = node->children;
2598 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002599 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2600 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002601 }
2602 if (IS_SCHEMA(child, "simpleType")) {
William M. Bracke7091952004-05-11 15:09:58 +00002603 if (hasRefType) {
2604 /* 3.2.3 : 4
2605 * type and <simpleType> must not both be present.
2606 *
2607 * TODO: XML_SCHEMAP_INVALID_ATTR_COMBINATION seems not to be
2608 * a proper error type here.
2609 */
2610 xmlSchemaPErr2(ctxt, node, child,
2611 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2612 "Attribute declaration %s has both (\"ref\" or "
2613 "\"type\") and <simpleType>\n", name, NULL);
2614 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00002615 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002616 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002617 }
2618 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002619 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2620 "attribute %s has unexpected content\n", name,
2621 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002622 }
2623
2624 return (ret);
2625}
2626
2627/**
2628 * xmlSchemaParseAttributeGroup:
2629 * @ctxt: a schema validation context
2630 * @schema: the schema being built
2631 * @node: a subtree containing XML Schema informations
2632 *
2633 * parse a XML schema Attribute Group declaration
2634 * *WARNING* this interface is highly subject to change
2635 *
2636 * Returns the attribute group or NULL in case of error.
2637 */
2638static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002639xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00002640 xmlSchemaPtr schema, xmlNodePtr node,
2641 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002642{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002643 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002644 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002645 xmlSchemaAttributePtr last = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002646 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002647 const xmlChar *oldcontainer;
2648 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002649
2650 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2651 return (NULL);
2652 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002653 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002654 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002655 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2656 if (ref == NULL) {
2657 xmlSchemaPErr2(ctxt, node, child,
2658 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2659 "AttributeGroup has no name nor ref\n", NULL,
2660 NULL);
2661 return (NULL);
2662 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002663 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2664 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002665 if (name == NULL) {
2666 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2667 return (NULL);
2668 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002669 }
2670 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2671 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002672 return (NULL);
2673 }
2674 ret->ref = ref;
2675 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002676 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00002677 if (topLevel)
2678 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002679 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002680 child = node->children;
2681 ctxt->container = name;
2682 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002683 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2684 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002685 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002686 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
2687 /* Seems that this can be removed. */
2688 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00002689 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002690 (IS_SCHEMA(child, "attributeGroup"))) {
2691 attr = NULL;
2692 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00002693 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002694 } else if (IS_SCHEMA(child, "attributeGroup")) {
2695 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00002696 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002697 }
2698 if (attr != NULL) {
2699 if (last == NULL) {
2700 ret->attributes = attr;
2701 last = attr;
2702 } else {
2703 last->next = attr;
2704 last = attr;
2705 }
2706 }
2707 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002708 }
2709 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002710 TODO
2711 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002712 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002713 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002714 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002715 xmlSchemaPErr2(ctxt, node, child,
2716 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2717 "attribute group %s has unexpected content\n", name,
2718 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002719 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002720 ctxt->container = oldcontainer;
2721 return (ret);
2722}
2723
2724/**
2725 * xmlSchemaParseElement:
2726 * @ctxt: a schema validation context
2727 * @schema: the schema being built
2728 * @node: a subtree containing XML Schema informations
2729 *
2730 * parse a XML schema Element declaration
2731 * *WARNING* this interface is highly subject to change
2732 *
William M. Bracke7091952004-05-11 15:09:58 +00002733 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002734 */
2735static xmlSchemaElementPtr
2736xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00002737 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002738{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002739 const xmlChar *name, *fixed;
2740 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002741 xmlSchemaElementPtr ret;
2742 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002743 const xmlChar *oldcontainer;
2744 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002745 xmlAttrPtr attr;
2746
2747 /* 3.3.3 Constraints on XML Representations of Element Declarations */
2748 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002749
2750 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2751 return (NULL);
2752 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002753 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002754 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002755 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002756 /* 3.3.3 : 2.1
2757 * One of ref or name must be present, but not both
2758 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002759 if (ref == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00002760 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002761 XML_SCHEMAP_ELEM_NONAME_NOREF,
Daniel Veillard3646d642004-06-02 19:19:14 +00002762 "Element declaration has no name nor ref\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002763 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002764 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002765
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002766 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2767 name = (const xmlChar *) buf;
2768 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2769 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002770 const xmlChar *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002771
William M. Bracke7091952004-05-11 15:09:58 +00002772 /* Evaluate the target namespace */
2773 if (schema->targetNamespace != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002774 if (topLevel) {
William M. Bracke7091952004-05-11 15:09:58 +00002775 ns = schema->targetNamespace;
2776 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2777 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2778 BAD_CAST "qualified")) {
2779 ns = schema->targetNamespace;
2780 }
2781 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2782 ns = schema->targetNamespace;
2783 }
2784 }
2785 /*local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2786 ret = xmlSchemaAddElement(ctxt, schema, name, ns);
2787 /* 3.3.3 : 2.1
2788 * One of ref or name must be present, but not both
2789 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002790 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00002791 xmlSchemaPErr(ctxt, node,
2792 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2793 "Element declaration has both, \"name\" and "
2794 "\"ref\"\n", NULL, NULL);
2795 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002796 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002797 if (ret != NULL)
2798 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002799 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002800 return (NULL);
2801 }
2802 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2803 ret->ref = ref;
2804 ret->refNs = refNs;
2805 if (ref != NULL)
2806 ret->flags |= XML_SCHEMAS_ELEM_REF;
William M. Bracke7091952004-05-11 15:09:58 +00002807
2808 /* 3.3.3 : 2.2 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002809 if ((!topLevel) && (ref != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00002810 attr = node->properties;
2811 while (attr != NULL) {
2812 if ((attr->ns == NULL) &&
2813 (!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
2814 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
2815 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
2816 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
2817
2818 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2819 "Element declaration %s: only minOccurs, maxOccurs "
2820 "and id are allowed in addition to ref\n",
2821 ret->name, NULL);
2822 }
2823 attr = attr->next;
2824 }
2825 }
2826
Daniel Veillard3646d642004-06-02 19:19:14 +00002827 if (topLevel) {
2828 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002829 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Daniel Veillard3646d642004-06-02 19:19:14 +00002830 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002831 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2832 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2833 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Daniel Veillard3646d642004-06-02 19:19:14 +00002834 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillard4255d502002-04-16 15:50:10 +00002835 ctxt->container = name;
2836
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002837 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002838 ret->namedType =
William M. Bracke7091952004-05-11 15:09:58 +00002839 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002840 ret->substGroup =
2841 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2842 &(ret->substGroupNs));
Daniel Veillard3646d642004-06-02 19:19:14 +00002843 if ((ret->substGroup != NULL) && (!topLevel)) {
William M. Bracke7091952004-05-11 15:09:58 +00002844 /* 3.3.6 : 3 */
2845 /*
2846 * TODO: This seems to be redundant, since the schema for schemas
2847 * already prohibits the use of the "substitutionGroup" attribute
2848 * in local element declarations.
2849 */
2850 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2851 "Element declaration %s: substitutionGroup is allowed "
2852 "on top-level declarations only\n", ret->name, NULL);
2853
2854 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002855 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002856 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2857 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002858
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002859 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002860 if ((ret->value != NULL) && (fixed != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00002861 /* 3.3.3 : 1
2862 * default and fixed must not both be present.
2863 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002864 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2865 "Element %s has both default and fixed\n",
2866 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002867 } else if (fixed != NULL) {
2868 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002869 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002870 }
2871
2872 child = node->children;
2873 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002874 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2875 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002876 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002877
William M. Bracke7091952004-05-11 15:09:58 +00002878 if (ref != NULL) {
2879 /* 3.3.3 (2.2) */
2880 while (child != NULL) {
2881 if ((IS_SCHEMA(child, "complexType")) ||
2882 (IS_SCHEMA(child, "simpleType")) ||
2883 (IS_SCHEMA(child, "unique")) ||
2884 (IS_SCHEMA(child, "key")) ||
2885 (IS_SCHEMA(child, "keyref"))) {
2886
2887 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_REF_AND_CONTENT,
2888 "Element declaration %s: only annotation is "
2889 "allowed as content in addition to ref\n",
2890 ret->name, NULL);
2891 } else {
2892 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2893 "element %s has unexpected content\n", name, NULL);
2894 }
2895 child = child->next;
2896 }
2897 } else {
2898 if (IS_SCHEMA(child, "complexType")) {
2899 /* 3.3.3 : 3
2900 * type and either <simpleType> or <complexType> are mutually
2901 * exclusive
2902 */
2903 if (ret->namedType != NULL) {
2904 xmlSchemaPErr2(ctxt, node, child,
2905 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2906 "Element declaration %s has both \"type\" "
2907 "and a local complex type\n",
2908 ret->name, NULL);
2909 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00002910 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00002911 child = child->next;
2912 } else if (IS_SCHEMA(child, "simpleType")) {
2913 /* 3.3.3 : 3
2914 * type and either <simpleType> or <complexType> are
2915 * mutually exclusive
2916 */
2917 if (ret->namedType != NULL) {
2918 xmlSchemaPErr2(ctxt, node, child,
2919 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2920 "Element declaration %s has both \"type\" "
2921 "and a local simple type\n",
2922 ret->name, NULL);
2923 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00002924 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00002925 child = child->next;
2926 }
2927
2928 while ((IS_SCHEMA(child, "unique")) ||
2929 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2930 TODO child = child->next;
2931 }
2932 if (child != NULL) {
2933 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2934 "element %s has unexpected content\n", name, NULL);
2935 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002936 }
2937
2938 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002939 return (ret);
2940}
2941
2942/**
2943 * xmlSchemaParseUnion:
2944 * @ctxt: a schema validation context
2945 * @schema: the schema being built
2946 * @node: a subtree containing XML Schema informations
2947 *
2948 * parse a XML schema Union definition
2949 * *WARNING* this interface is highly subject to change
2950 *
William M. Bracke7091952004-05-11 15:09:58 +00002951 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002952 * 1 in case of success.
2953 */
2954static xmlSchemaTypePtr
2955xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002956 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002957{
2958 xmlSchemaTypePtr type, subtype, last = NULL;
2959 xmlNodePtr child = NULL;
2960 xmlChar name[30];
2961
2962 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2963 return (NULL);
2964
2965
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002966 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002967 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002968 if (type == NULL)
2969 return (NULL);
2970 type->node = node;
Daniel Veillard377e1a92004-04-16 16:30:05 +00002971 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002972 type->id = xmlSchemaGetProp(ctxt, node, "id");
2973 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002974
2975 child = node->children;
2976 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002977 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2978 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002979 }
2980 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002981 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00002982 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002983 if (subtype != NULL) {
2984 if (last == NULL) {
2985 type->subtypes = subtype;
2986 last = subtype;
2987 } else {
2988 last->next = subtype;
2989 last = subtype;
2990 }
2991 last->next = NULL;
2992 }
2993 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002994 }
2995 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002996 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2997 "Union %s has unexpected content\n", type->name,
2998 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002999 }
3000 return (type);
3001}
3002
3003/**
3004 * xmlSchemaParseList:
3005 * @ctxt: a schema validation context
3006 * @schema: the schema being built
3007 * @node: a subtree containing XML Schema informations
3008 *
3009 * parse a XML schema List definition
3010 * *WARNING* this interface is highly subject to change
3011 *
William M. Bracke7091952004-05-11 15:09:58 +00003012 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003013 * 1 in case of success.
3014 */
3015static xmlSchemaTypePtr
3016xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003017 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003018{
3019 xmlSchemaTypePtr type, subtype;
3020 xmlNodePtr child = NULL;
3021 xmlChar name[30];
3022
3023 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3024 return (NULL);
3025
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003026 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003027 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003028 if (type == NULL)
3029 return (NULL);
3030 type->node = node;
3031 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003032 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003033 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
3034
3035 child = node->children;
3036 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003037 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3038 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003039 }
William M. Bracke7091952004-05-11 15:09:58 +00003040
Daniel Veillard4255d502002-04-16 15:50:10 +00003041 subtype = NULL;
3042 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003043 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00003044 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003045 child = child->next;
3046 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003047 }
3048 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003049 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
3050 "List %s has unexpected content\n", type->name,
3051 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003052 }
3053 return (type);
3054}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003055
Daniel Veillard4255d502002-04-16 15:50:10 +00003056/**
3057 * xmlSchemaParseSimpleType:
3058 * @ctxt: a schema validation context
3059 * @schema: the schema being built
3060 * @node: a subtree containing XML Schema informations
3061 *
3062 * parse a XML schema Simple Type definition
3063 * *WARNING* this interface is highly subject to change
3064 *
William M. Bracke7091952004-05-11 15:09:58 +00003065 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003066 * 1 in case of success.
3067 */
3068static xmlSchemaTypePtr
3069xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003070 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003071{
3072 xmlSchemaTypePtr type, subtype;
3073 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003074 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00003075
3076 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3077 return (NULL);
3078
3079
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003080 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003081 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003082 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003083
William M. Bracke7091952004-05-11 15:09:58 +00003084 snprintf(buf, 99, "simpleType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003085 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00003086 } else {
3087 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
3088 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003089 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003090 if (type == NULL)
3091 return (NULL);
3092 type->node = node;
3093 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillard3646d642004-06-02 19:19:14 +00003094 if (topLevel)
3095 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003096 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003097
3098 child = node->children;
3099 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003100 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3101 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003102 }
3103 subtype = NULL;
3104 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003105 subtype = (xmlSchemaTypePtr)
3106 xmlSchemaParseRestriction(ctxt, schema, child, 1);
3107 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003108 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003109 subtype = (xmlSchemaTypePtr)
3110 xmlSchemaParseList(ctxt, schema, child);
3111 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003112 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003113 subtype = (xmlSchemaTypePtr)
3114 xmlSchemaParseUnion(ctxt, schema, child);
3115 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003116 }
3117 type->subtypes = subtype;
William M. Bracke7091952004-05-11 15:09:58 +00003118 if (subtype == NULL) {
3119 xmlSchemaPErr2(ctxt, node, child,
3120 XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD,
3121 "SimpleType %s does not define a variety\n",
3122 type->name, NULL);
3123 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003124 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003125 xmlSchemaPErr2(ctxt, node, child,
3126 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
3127 "SimpleType %s has unexpected content\n",
3128 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003129 }
3130
3131 return (type);
3132}
3133
3134
3135/**
3136 * xmlSchemaParseGroup:
3137 * @ctxt: a schema validation context
3138 * @schema: the schema being built
3139 * @node: a subtree containing XML Schema informations
3140 *
3141 * parse a XML schema Group definition
3142 * *WARNING* this interface is highly subject to change
3143 *
William M. Bracke7091952004-05-11 15:09:58 +00003144 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003145 * 1 in case of success.
3146 */
3147static xmlSchemaTypePtr
3148xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003149 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003150{
3151 xmlSchemaTypePtr type, subtype;
3152 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003153 const xmlChar *name;
3154 const xmlChar *ref = NULL, *refNs = NULL;
3155 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003156
3157 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3158 return (NULL);
3159
3160
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003161 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003162 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003163 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
3164 if (ref == NULL) {
3165 xmlSchemaPErr2(ctxt, node, child,
3166 XML_SCHEMAP_GROUP_NONAME_NOREF,
3167 "Group has no name nor ref\n", NULL, NULL);
3168 return (NULL);
3169 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003170 if (refNs == NULL)
3171 refNs = schema->targetNamespace;
3172 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
3173 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00003174 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003175 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003176 if (type == NULL)
3177 return (NULL);
3178 type->node = node;
3179 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00003180 if (topLevel)
3181 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003182 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003183 type->ref = ref;
3184 type->refNs = refNs;
3185 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3186 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3187
3188 child = node->children;
3189 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003190 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3191 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003192 }
3193 subtype = NULL;
3194 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003195 subtype = (xmlSchemaTypePtr)
3196 xmlSchemaParseAll(ctxt, schema, child);
3197 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003198 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003199 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3200 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003201 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003202 subtype = (xmlSchemaTypePtr)
3203 xmlSchemaParseSequence(ctxt, schema, child);
3204 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003205 }
3206 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003207 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003208 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003209 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
3210 "Group %s has unexpected content\n", type->name,
3211 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003212 }
3213
3214 return (type);
3215}
3216
3217/**
3218 * xmlSchemaParseAll:
3219 * @ctxt: a schema validation context
3220 * @schema: the schema being built
3221 * @node: a subtree containing XML Schema informations
3222 *
3223 * parse a XML schema All definition
3224 * *WARNING* this interface is highly subject to change
3225 *
William M. Bracke7091952004-05-11 15:09:58 +00003226 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003227 * 1 in case of success.
3228 */
3229static xmlSchemaTypePtr
3230xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003231 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003232{
3233 xmlSchemaTypePtr type, subtype, last = NULL;
3234 xmlNodePtr child = NULL;
3235 xmlChar name[30];
3236
3237 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3238 return (NULL);
3239
3240
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003241 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003242 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003243 if (type == NULL)
3244 return (NULL);
3245 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00003246 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003247 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003248 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00003249 if (type->minOccurs > 1)
3250 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
3251 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003252 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00003253 if (type->maxOccurs > 1)
3254 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
3255 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003256
3257 child = node->children;
3258 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003259 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3260 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003261 }
3262 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003263 subtype = (xmlSchemaTypePtr)
3264 xmlSchemaParseElement(ctxt, schema, child, 0);
3265 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00003266 if (subtype->minOccurs > 1)
3267 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
3268 "invalid value for minOccurs (must be 0 or 1)\n",
3269 NULL, NULL);
3270 if (subtype->maxOccurs > 1)
3271 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
3272 "invalid value for maxOccurs (must be 0 or 1)\n",
3273 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003274 if (last == NULL) {
3275 type->subtypes = subtype;
3276 last = subtype;
3277 } else {
3278 last->next = subtype;
3279 last = subtype;
3280 }
3281 last->next = NULL;
3282 }
3283 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003284 }
3285 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003286 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
3287 "All %s has unexpected content\n", type->name,
3288 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003289 }
3290
3291 return (type);
3292}
3293
3294/**
Daniel Veillard1d913862003-11-21 00:28:39 +00003295 * xmlSchemaImportSchema
3296 *
3297 * @ctxt: a schema validation context
3298 * @schemaLocation: an URI defining where to find the imported schema
3299 *
3300 * import a XML schema
3301 * *WARNING* this interface is highly subject to change
3302 *
3303 * Returns -1 in case of error and 1 in case of success.
3304 */
3305static xmlSchemaImportPtr
3306xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
3307 const xmlChar *schemaLocation)
3308{
3309 xmlSchemaImportPtr import;
3310 xmlSchemaParserCtxtPtr newctxt;
3311
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003312 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00003313 if (newctxt == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003314 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00003315 NULL);
3316 return (NULL);
3317 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003318 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
3319 /* Keep the same dictionnary for parsing, really */
3320 xmlDictReference(ctxt->dict);
3321 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003322 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003323 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
3324
Daniel Veillard1d913862003-11-21 00:28:39 +00003325 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
3326 ctxt->userData);
3327
3328 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
3329 if (import == NULL) {
3330 xmlSchemaPErrMemory(NULL, "allocating imported schema",
3331 NULL);
3332 xmlSchemaFreeParserCtxt(newctxt);
3333 return (NULL);
3334 }
3335
3336 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003337 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00003338 import->schema = xmlSchemaParse(newctxt);
3339
3340 if (import->schema == NULL) {
3341 /* FIXME use another error enum here ? */
3342 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
3343 "failed to import schema at location %s\n",
3344 schemaLocation, NULL);
3345
3346 xmlSchemaFreeParserCtxt(newctxt);
3347 if (import->schemaLocation != NULL)
3348 xmlFree((xmlChar *)import->schemaLocation);
3349 xmlFree(import);
3350 return NULL;
3351 }
3352
3353 xmlSchemaFreeParserCtxt(newctxt);
3354 return import;
3355}
3356
3357
3358/**
Daniel Veillard5a872412002-05-22 06:40:27 +00003359 * xmlSchemaParseImport:
3360 * @ctxt: a schema validation context
3361 * @schema: the schema being built
3362 * @node: a subtree containing XML Schema informations
3363 *
3364 * parse a XML schema Import definition
3365 * *WARNING* this interface is highly subject to change
3366 *
William M. Bracke7091952004-05-11 15:09:58 +00003367 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard5a872412002-05-22 06:40:27 +00003368 * 1 in case of success.
3369 */
3370static int
3371xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003372 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00003373{
3374 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00003375 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003376 const xmlChar *namespace;
3377 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00003378 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00003379 xmlURIPtr check;
3380
Daniel Veillard1d913862003-11-21 00:28:39 +00003381
Daniel Veillard5a872412002-05-22 06:40:27 +00003382 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3383 return (-1);
3384
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003385 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00003386 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003387 check = xmlParseURI((const char *) namespace);
3388 if (check == NULL) {
3389 xmlSchemaPErr2(ctxt, node, child,
3390 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
3391 "Import namespace attribute is not an URI: %s\n",
3392 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003393 return (-1);
3394 } else {
3395 xmlFreeURI(check);
3396 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003397 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003398 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00003399 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003400 xmlChar *base = NULL;
3401 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003402 check = xmlParseURI((const char *) schemaLocation);
3403 if (check == NULL) {
3404 xmlSchemaPErr2(ctxt, node, child,
3405 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
3406 "Import schemaLocation attribute is not an URI: %s\n",
3407 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003408 return (-1);
3409 } else {
3410 xmlFreeURI(check);
3411 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003412 base = xmlNodeGetBase(node->doc, node);
3413 if (base == NULL) {
3414 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3415 } else {
3416 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003417 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00003418 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003419 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003420 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3421 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00003422 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003423 }
3424 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003425 schema->schemasImports = xmlHashCreate(10);
3426 if (schema->schemasImports == NULL) {
3427 xmlSchemaPErr2(ctxt, node, child,
3428 XML_SCHEMAP_FAILED_BUILD_IMPORT,
3429 "Internal: failed to build import table\n",
3430 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003431 return (-1);
3432 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003433 }
3434 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003435 import = xmlHashLookup(schema->schemasImports,
3436 XML_SCHEMAS_DEFAULT_NAMESPACE);
3437 if (import != NULL)
3438 previous = import->schemaLocation;
3439 else
3440 previous = NULL;
3441
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003442 if (schemaLocation != NULL) {
3443 if (previous != NULL) {
3444 if (!xmlStrEqual(schemaLocation, previous)) {
3445 xmlSchemaPErr2(ctxt, node, child,
3446 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003447 "Redefining import for default namespace "
3448 "with a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003449 schemaLocation, NULL);
3450 }
3451 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003452 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3453 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003454 return (-1);
3455 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003456 xmlHashAddEntry(schema->schemasImports,
3457 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00003458 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003459 }
3460 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003461 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003462 import = xmlHashLookup(schema->schemasImports, namespace);
3463 if (import != NULL)
3464 previous = import->schemaLocation;
3465 else
3466 previous = NULL;
3467
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003468 if (schemaLocation != NULL) {
3469 if (previous != NULL) {
3470 if (!xmlStrEqual(schemaLocation, previous)) {
3471 xmlSchemaPErr2(ctxt, node, child,
3472 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003473 "Redefining import for namespace %s with "
3474 "a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003475 namespace, schemaLocation);
3476 }
3477 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003478 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3479 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003480 return (-1);
3481 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003482 if (!xmlStrEqual(import->schema->targetNamespace, namespace)) {
3483 if (namespace == NULL) {
3484 if (import->schema->targetNamespace != NULL) {
3485 xmlSchemaPErr(ctxt, node, XML_SCHRMAP_SRC_IMPORT_3_2,
3486 "There is no namespace attribute on the <import> "
3487 "element information item, so the imported document "
3488 "must have no targetNamespace attribute.\n",
3489 NULL, NULL);
3490 }
3491 } else {
3492 if (import->schema->targetNamespace != NULL) {
3493 xmlSchemaPErr(ctxt, node, XML_SCHRMAP_SRC_IMPORT_3_1,
3494 "The namespace attribute \"%s\" of an <import> "
3495 "element information item must be identical to the "
3496 "targetNamespace attribute \"%s\" of the "
3497 "imported document.\n",
3498 namespace, import->schema->targetNamespace);
3499 } else {
3500 xmlSchemaPErr(ctxt, node, XML_SCHRMAP_SRC_IMPORT_3_1,
3501 "The namespace attribute on the <import> "
3502 "element information item, requires the imported "
3503 "document to have a targetNamespace attribute "
3504 "with the value \"%s\".\n",
3505 namespace, NULL);
3506 }
3507 }
3508 xmlSchemaFreeImport(import);
3509 return (-1);
3510 }
3511
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003512 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00003513 namespace, import);
Daniel Veillard3646d642004-06-02 19:19:14 +00003514
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003515 }
3516 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003517 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003518
3519 child = node->children;
3520 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003521 /*
3522 * the annotations here are simply discarded ...
3523 */
3524 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00003525 }
3526 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003527 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
3528 "Import has unexpected content\n", NULL, NULL);
3529 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003530 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003531 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003532}
3533
3534/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003535 * xmlSchemaCleanupDoc:
3536 * @ctxt: a schema validation context
3537 * @node: the root of the document.
3538 *
3539 * removes unwanted nodes in a schemas document tree
3540 */
3541static void
3542xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
3543{
3544 xmlNodePtr delete, cur;
3545
3546 if ((ctxt == NULL) || (root == NULL)) return;
3547
3548 /*
3549 * Remove all the blank text nodes
3550 */
3551 delete = NULL;
3552 cur = root;
3553 while (cur != NULL) {
3554 if (delete != NULL) {
3555 xmlUnlinkNode(delete);
3556 xmlFreeNode(delete);
3557 delete = NULL;
3558 }
3559 if (cur->type == XML_TEXT_NODE) {
3560 if (IS_BLANK_NODE(cur)) {
3561 if (xmlNodeGetSpacePreserve(cur) != 1) {
3562 delete = cur;
3563 }
3564 }
3565 } else if ((cur->type != XML_ELEMENT_NODE) &&
3566 (cur->type != XML_CDATA_SECTION_NODE)) {
3567 delete = cur;
3568 goto skip_children;
3569 }
3570
3571 /*
3572 * Skip to next node
3573 */
3574 if (cur->children != NULL) {
3575 if ((cur->children->type != XML_ENTITY_DECL) &&
3576 (cur->children->type != XML_ENTITY_REF_NODE) &&
3577 (cur->children->type != XML_ENTITY_NODE)) {
3578 cur = cur->children;
3579 continue;
3580 }
3581 }
3582 skip_children:
3583 if (cur->next != NULL) {
3584 cur = cur->next;
3585 continue;
3586 }
3587
3588 do {
3589 cur = cur->parent;
3590 if (cur == NULL)
3591 break;
3592 if (cur == root) {
3593 cur = NULL;
3594 break;
3595 }
3596 if (cur->next != NULL) {
3597 cur = cur->next;
3598 break;
3599 }
3600 } while (cur != NULL);
3601 }
3602 if (delete != NULL) {
3603 xmlUnlinkNode(delete);
3604 xmlFreeNode(delete);
3605 delete = NULL;
3606 }
3607}
3608
3609/**
3610 * xmlSchemaParseSchemaTopLevel:
3611 * @ctxt: a schema validation context
3612 * @schema: the schemas
3613 * @nodes: the list of top level nodes
3614 *
3615 * Returns the internal XML Schema structure built from the resource or
3616 * NULL in case of error
3617 */
3618static void
3619xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
3620 xmlSchemaPtr schema, xmlNodePtr nodes)
3621{
3622 xmlNodePtr child;
3623 xmlSchemaAnnotPtr annot;
3624
3625 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
3626 return;
3627
3628 child = nodes;
3629 while ((IS_SCHEMA(child, "include")) ||
3630 (IS_SCHEMA(child, "import")) ||
3631 (IS_SCHEMA(child, "redefine")) ||
3632 (IS_SCHEMA(child, "annotation"))) {
3633 if (IS_SCHEMA(child, "annotation")) {
3634 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3635 if (schema->annot == NULL)
3636 schema->annot = annot;
3637 else
3638 xmlSchemaFreeAnnot(annot);
3639 } else if (IS_SCHEMA(child, "import")) {
3640 xmlSchemaParseImport(ctxt, schema, child);
3641 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003642 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003643 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003644 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003645 } else if (IS_SCHEMA(child, "redefine")) {
3646 TODO
3647 }
3648 child = child->next;
3649 }
3650 while (child != NULL) {
3651 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003652 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003653 child = child->next;
3654 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003655 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003656 child = child->next;
3657 } else if (IS_SCHEMA(child, "element")) {
3658 xmlSchemaParseElement(ctxt, schema, child, 1);
3659 child = child->next;
3660 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003661 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003662 child = child->next;
3663 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003664 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003665 child = child->next;
3666 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003667 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003668 child = child->next;
3669 } else if (IS_SCHEMA(child, "notation")) {
3670 xmlSchemaParseNotation(ctxt, schema, child);
3671 child = child->next;
3672 } else {
3673 xmlSchemaPErr2(ctxt, NULL, child,
3674 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3675 "Schemas: unexpected element %s here \n",
3676 child->name, NULL);
3677 child = child->next;
3678 }
3679 while (IS_SCHEMA(child, "annotation")) {
3680 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3681 if (schema->annot == NULL)
3682 schema->annot = annot;
3683 else
3684 xmlSchemaFreeAnnot(annot);
3685 child = child->next;
3686 }
3687 }
3688}
3689
3690/**
3691 * xmlSchemaParseInclude:
3692 * @ctxt: a schema validation context
3693 * @schema: the schema being built
3694 * @node: a subtree containing XML Schema informations
3695 *
3696 * parse a XML schema Include definition
3697 *
William M. Bracke7091952004-05-11 15:09:58 +00003698 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003699 * 1 in case of success.
3700 */
3701static int
3702xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3703 xmlNodePtr node)
3704{
3705 xmlNodePtr child = NULL;
3706 const xmlChar *schemaLocation;
3707 xmlURIPtr check;
3708 xmlDocPtr doc;
3709 xmlNodePtr root;
3710 xmlSchemaIncludePtr include;
3711
3712
3713 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3714 return (-1);
3715
3716 /*
3717 * Preliminary step, extract the URI-Reference for the include and
3718 * make an URI from the base.
3719 */
3720 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
3721 if (schemaLocation != NULL) {
3722 xmlChar *base = NULL;
3723 xmlChar *URI = NULL;
3724 check = xmlParseURI((const char *) schemaLocation);
3725 if (check == NULL) {
3726 xmlSchemaPErr2(ctxt, node, child,
3727 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3728 "Include schemaLocation attribute is not an URI: %s\n",
3729 schemaLocation, NULL);
3730 return (-1);
3731 } else {
3732 xmlFreeURI(check);
3733 }
3734 base = xmlNodeGetBase(node->doc, node);
3735 if (base == NULL) {
3736 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3737 } else {
3738 URI = xmlBuildURI(schemaLocation, base);
3739 xmlFree(base);
3740 }
3741 if (URI != NULL) {
3742 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3743 xmlFree(URI);
3744 }
3745 } else {
3746 xmlSchemaPErr2(ctxt, node, child,
3747 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3748 "Include schemaLocation attribute missing\n",
3749 NULL, NULL);
3750 return (-1);
3751 }
3752
3753 child = node->children;
3754 while (IS_SCHEMA(child, "annotation")) {
3755 /*
3756 * the annotations here are simply discarded ...
3757 */
3758 child = child->next;
3759 }
3760 if (child != NULL) {
3761 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3762 "Include has unexpected content\n", NULL, NULL);
3763 return (-1);
3764 }
3765
3766 /*
3767 * First step is to parse the input document into an DOM/Infoset
3768 */
3769 doc = xmlReadFile((const char *) schemaLocation, NULL,
3770 SCHEMAS_PARSE_OPTIONS);
3771 if (doc == NULL) {
3772 xmlSchemaPErr(ctxt, NULL,
3773 XML_SCHEMAP_FAILED_LOAD,
3774 "xmlSchemaParse: could not load %s\n",
3775 ctxt->URL, NULL);
3776 return(-1);
3777 }
3778
3779 /*
3780 * Then extract the root of the schema
3781 */
3782 root = xmlDocGetRootElement(doc);
3783 if (root == NULL) {
3784 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3785 XML_SCHEMAP_NOROOT,
3786 "schemas %s has no root", schemaLocation, NULL);
3787 xmlFreeDoc(doc);
3788 return (-1);
3789 }
3790
3791 /*
3792 * Remove all the blank text nodes
3793 */
3794 xmlSchemaCleanupDoc(ctxt, root);
3795
3796 /*
3797 * Check the schemas top level element
3798 */
3799 if (!IS_SCHEMA(root, "schema")) {
3800 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3801 XML_SCHEMAP_NOT_SCHEMA,
3802 "File %s is not a schemas", schemaLocation, NULL);
3803 xmlFreeDoc(doc);
3804 return (-1);
3805 }
3806
3807 /*
3808 * register the include
3809 */
3810 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3811 if (include == NULL) {
3812 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3813 xmlFreeDoc(doc);
3814 return (-1);
3815 }
3816
3817 memset(include, 0, sizeof(xmlSchemaInclude));
3818 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3819 include->doc = doc;
3820 include->next = schema->includes;
3821 schema->includes = include;
3822
3823
3824 /*
3825 * parse the declarations in the included file like if they
3826 * were in the original file.
3827 */
3828 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3829
3830 return (1);
3831}
3832
3833/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003834 * xmlSchemaParseChoice:
3835 * @ctxt: a schema validation context
3836 * @schema: the schema being built
3837 * @node: a subtree containing XML Schema informations
3838 *
3839 * parse a XML schema Choice definition
3840 * *WARNING* this interface is highly subject to change
3841 *
William M. Bracke7091952004-05-11 15:09:58 +00003842 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003843 * 1 in case of success.
3844 */
3845static xmlSchemaTypePtr
3846xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003847 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003848{
3849 xmlSchemaTypePtr type, subtype, last = NULL;
3850 xmlNodePtr child = NULL;
3851 xmlChar name[30];
3852
3853 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3854 return (NULL);
3855
3856
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003857 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003858 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003859 if (type == NULL)
3860 return (NULL);
3861 type->node = node;
3862 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003863 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003864 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3865 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3866
3867 child = node->children;
3868 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003869 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3870 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003871 }
3872 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003873 (IS_SCHEMA(child, "group")) ||
3874 (IS_SCHEMA(child, "any")) ||
3875 (IS_SCHEMA(child, "choice")) ||
3876 (IS_SCHEMA(child, "sequence"))) {
3877 subtype = NULL;
3878 if (IS_SCHEMA(child, "element")) {
3879 subtype = (xmlSchemaTypePtr)
3880 xmlSchemaParseElement(ctxt, schema, child, 0);
3881 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003882 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003883 } else if (IS_SCHEMA(child, "any")) {
3884 subtype = xmlSchemaParseAny(ctxt, schema, child);
3885 } else if (IS_SCHEMA(child, "sequence")) {
3886 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3887 } else if (IS_SCHEMA(child, "choice")) {
3888 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3889 }
3890 if (subtype != NULL) {
3891 if (last == NULL) {
3892 type->subtypes = subtype;
3893 last = subtype;
3894 } else {
3895 last->next = subtype;
3896 last = subtype;
3897 }
3898 last->next = NULL;
3899 }
3900 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003901 }
3902 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003903 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3904 "Choice %s has unexpected content\n", type->name,
3905 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003906 }
3907
3908 return (type);
3909}
3910
3911/**
3912 * xmlSchemaParseSequence:
3913 * @ctxt: a schema validation context
3914 * @schema: the schema being built
3915 * @node: a subtree containing XML Schema informations
3916 *
3917 * parse a XML schema Sequence definition
3918 * *WARNING* this interface is highly subject to change
3919 *
William M. Bracke7091952004-05-11 15:09:58 +00003920 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003921 * 1 in case of success.
3922 */
3923static xmlSchemaTypePtr
3924xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003925 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003926{
3927 xmlSchemaTypePtr type, subtype, last = NULL;
3928 xmlNodePtr child = NULL;
3929 xmlChar name[30];
3930
3931 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3932 return (NULL);
3933
3934
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003935 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003936 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003937 if (type == NULL)
3938 return (NULL);
3939 type->node = node;
3940 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003941 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003942 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3943 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3944
3945 child = node->children;
3946 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003947 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3948 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003949 }
3950 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003951 (IS_SCHEMA(child, "group")) ||
3952 (IS_SCHEMA(child, "any")) ||
3953 (IS_SCHEMA(child, "choice")) ||
3954 (IS_SCHEMA(child, "sequence"))) {
3955 subtype = NULL;
3956 if (IS_SCHEMA(child, "element")) {
3957 subtype = (xmlSchemaTypePtr)
3958 xmlSchemaParseElement(ctxt, schema, child, 0);
3959 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003960 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003961 } else if (IS_SCHEMA(child, "any")) {
3962 subtype = xmlSchemaParseAny(ctxt, schema, child);
3963 } else if (IS_SCHEMA(child, "choice")) {
3964 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3965 } else if (IS_SCHEMA(child, "sequence")) {
3966 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3967 }
3968 if (subtype != NULL) {
3969 if (last == NULL) {
3970 type->subtypes = subtype;
3971 last = subtype;
3972 } else {
3973 last->next = subtype;
3974 last = subtype;
3975 }
3976 last->next = NULL;
3977 }
3978 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003979 }
3980 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003981 xmlSchemaPErr2(ctxt, node, child,
3982 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3983 "Sequence %s has unexpected content\n", type->name,
3984 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003985 }
3986
3987 return (type);
3988}
3989
3990/**
3991 * xmlSchemaParseRestriction:
3992 * @ctxt: a schema validation context
3993 * @schema: the schema being built
3994 * @node: a subtree containing XML Schema informations
3995 * @simple: is that part of a simple type.
3996 *
3997 * parse a XML schema Restriction definition
3998 * *WARNING* this interface is highly subject to change
3999 *
4000 * Returns the type definition or NULL in case of error
4001 */
4002static xmlSchemaTypePtr
4003xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4004 xmlNodePtr node, int simple)
4005{
4006 xmlSchemaTypePtr type, subtype;
4007 xmlSchemaFacetPtr facet, lastfacet = NULL;
4008 xmlNodePtr child = NULL;
4009 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004010 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00004011
4012 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4013 return (NULL);
4014
4015 oldcontainer = ctxt->container;
4016
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004017 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004018 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004019 if (type == NULL)
4020 return (NULL);
4021 type->node = node;
4022 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004023 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004024 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
4025 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004026 xmlSchemaPErr2(ctxt, node, child,
4027 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
4028 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004029 }
4030 ctxt->container = name;
4031
4032 child = node->children;
4033 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004034 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4035 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004036 }
4037 subtype = NULL;
4038
4039 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004040 subtype = (xmlSchemaTypePtr)
4041 xmlSchemaParseAll(ctxt, schema, child);
4042 child = child->next;
4043 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004044 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004045 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4046 child = child->next;
4047 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004048 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004049 subtype = (xmlSchemaTypePtr)
4050 xmlSchemaParseSequence(ctxt, schema, child);
4051 child = child->next;
4052 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004053 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004054 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004055 xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004056 child = child->next;
4057 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004058 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004059 if (IS_SCHEMA(child, "simpleType")) {
4060 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004061 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004062 child = child->next;
4063 type->baseType = subtype;
4064 }
4065 /*
4066 * Facets
4067 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004068 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004069 (IS_SCHEMA(child, "minExclusive")) ||
4070 (IS_SCHEMA(child, "maxInclusive")) ||
4071 (IS_SCHEMA(child, "maxExclusive")) ||
4072 (IS_SCHEMA(child, "totalDigits")) ||
4073 (IS_SCHEMA(child, "fractionDigits")) ||
4074 (IS_SCHEMA(child, "pattern")) ||
4075 (IS_SCHEMA(child, "enumeration")) ||
4076 (IS_SCHEMA(child, "whiteSpace")) ||
4077 (IS_SCHEMA(child, "length")) ||
4078 (IS_SCHEMA(child, "maxLength")) ||
4079 (IS_SCHEMA(child, "minLength"))) {
4080 facet = xmlSchemaParseFacet(ctxt, schema, child);
4081 if (facet != NULL) {
4082 if (lastfacet == NULL) {
4083 type->facets = facet;
4084 lastfacet = facet;
4085 } else {
4086 lastfacet->next = facet;
4087 lastfacet = facet;
4088 }
4089 lastfacet->next = NULL;
4090 }
4091 child = child->next;
4092 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004093 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004094 /* TODO: a restriction of simpleType does not contain any
4095 * attribute declarations.
4096 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004097 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
4098 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004099 xmlSchemaPErr2(ctxt, node, child,
4100 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
4101 "Restriction %s has unexpected content\n",
4102 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004103 }
4104 ctxt->container = oldcontainer;
4105 return (type);
4106}
4107
4108/**
4109 * xmlSchemaParseExtension:
4110 * @ctxt: a schema validation context
4111 * @schema: the schema being built
4112 * @node: a subtree containing XML Schema informations
4113 *
4114 * parse a XML schema Extension definition
4115 * *WARNING* this interface is highly subject to change
4116 *
4117 * Returns the type definition or NULL in case of error
4118 */
4119static xmlSchemaTypePtr
4120xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004121 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004122{
4123 xmlSchemaTypePtr type, subtype;
4124 xmlNodePtr child = NULL;
4125 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004126 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00004127
4128 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4129 return (NULL);
4130
4131 oldcontainer = ctxt->container;
4132
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004133 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004134 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004135 if (type == NULL)
4136 return (NULL);
4137 type->node = node;
4138 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004139 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004140 ctxt->container = name;
4141
4142 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
4143 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004144 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
4145 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004146 }
4147 child = node->children;
4148 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004149 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4150 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004151 }
4152 subtype = NULL;
4153
4154 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004155 subtype = xmlSchemaParseAll(ctxt, schema, child);
4156 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004157 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004158 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4159 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004160 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004161 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4162 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004163 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004164 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004165 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004166 }
4167 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004168 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004169 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
4170 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004171 xmlSchemaPErr2(ctxt, node, child,
4172 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
4173 "Extension %s has unexpected content\n", type->name,
4174 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004175 }
4176 ctxt->container = oldcontainer;
4177 return (type);
4178}
4179
4180/**
4181 * xmlSchemaParseSimpleContent:
4182 * @ctxt: a schema validation context
4183 * @schema: the schema being built
4184 * @node: a subtree containing XML Schema informations
4185 *
4186 * parse a XML schema SimpleContent definition
4187 * *WARNING* this interface is highly subject to change
4188 *
4189 * Returns the type definition or NULL in case of error
4190 */
4191static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004192xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
4193 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004194{
4195 xmlSchemaTypePtr type, subtype;
4196 xmlNodePtr child = NULL;
4197 xmlChar name[30];
4198
4199 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4200 return (NULL);
4201
William M. Bracke7091952004-05-11 15:09:58 +00004202 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004203 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004204 if (type == NULL)
4205 return (NULL);
4206 type->node = node;
4207 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004208 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004209
4210 child = node->children;
4211 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004212 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4213 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004214 }
4215 subtype = NULL;
4216 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004217 subtype = (xmlSchemaTypePtr)
4218 xmlSchemaParseRestriction(ctxt, schema, child, 0);
4219 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004220 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004221 subtype = (xmlSchemaTypePtr)
4222 xmlSchemaParseExtension(ctxt, schema, child);
4223 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004224 }
4225 type->subtypes = subtype;
4226 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004227 xmlSchemaPErr2(ctxt, node, child,
4228 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
4229 "SimpleContent %s has unexpected content\n",
4230 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004231 }
4232 return (type);
4233}
4234
4235/**
4236 * xmlSchemaParseComplexContent:
4237 * @ctxt: a schema validation context
4238 * @schema: the schema being built
4239 * @node: a subtree containing XML Schema informations
4240 *
4241 * parse a XML schema ComplexContent definition
4242 * *WARNING* this interface is highly subject to change
4243 *
4244 * Returns the type definition or NULL in case of error
4245 */
4246static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004247xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
4248 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004249{
4250 xmlSchemaTypePtr type, subtype;
4251 xmlNodePtr child = NULL;
4252 xmlChar name[30];
4253
4254 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4255 return (NULL);
4256
4257
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004258 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004259 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004260 if (type == NULL)
4261 return (NULL);
4262 type->node = node;
4263 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004264 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004265
4266 child = node->children;
4267 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004268 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4269 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004270 }
4271 subtype = NULL;
4272 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004273 subtype = (xmlSchemaTypePtr)
4274 xmlSchemaParseRestriction(ctxt, schema, child, 0);
4275 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004276 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004277 subtype = (xmlSchemaTypePtr)
4278 xmlSchemaParseExtension(ctxt, schema, child);
4279 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004280 }
4281 type->subtypes = subtype;
4282 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004283 xmlSchemaPErr2(ctxt, node, child,
4284 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
4285 "ComplexContent %s has unexpected content\n",
4286 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004287 }
4288 return (type);
4289}
4290
4291/**
4292 * xmlSchemaParseComplexType:
4293 * @ctxt: a schema validation context
4294 * @schema: the schema being built
4295 * @node: a subtree containing XML Schema informations
4296 *
4297 * parse a XML schema Complex Type definition
4298 * *WARNING* this interface is highly subject to change
4299 *
4300 * Returns the type definition or NULL in case of error
4301 */
4302static xmlSchemaTypePtr
4303xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004304 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004305{
4306 xmlSchemaTypePtr type, subtype;
4307 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004308 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00004309 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004310 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00004311
4312 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4313 return (NULL);
4314
4315 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004316 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004317 if (name == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00004318 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004319 name = (const xmlChar *)buf;
4320 type = xmlSchemaAddType(ctxt, schema, name, NULL);
4321 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004322
William M. Bracke7091952004-05-11 15:09:58 +00004323 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
4324 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004325 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004326 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004327 return (NULL);
4328 }
William M. Bracke7091952004-05-11 15:09:58 +00004329 if (xmlGetBooleanProp(ctxt, node, "mixed", 0))
4330 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004331
Daniel Veillard4255d502002-04-16 15:50:10 +00004332 type->node = node;
4333 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillard3646d642004-06-02 19:19:14 +00004334 if (topLevel)
4335 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004336 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004337 ctxt->container = name;
4338
4339 child = node->children;
4340 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004341 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4342 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004343 }
4344 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00004345 /* 3.4.3 : 2.2
4346 * Specifying mixed='true' when the <simpleContent>
4347 * alternative is chosen has no effect
4348 */
4349 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
4350 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004351 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
4352 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004353 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004354 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
4355 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004356 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004357 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004358
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004359 if (IS_SCHEMA(child, "all")) {
4360 subtype = xmlSchemaParseAll(ctxt, schema, child);
4361 child = child->next;
4362 } else if (IS_SCHEMA(child, "choice")) {
4363 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4364 child = child->next;
4365 } else if (IS_SCHEMA(child, "sequence")) {
4366 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4367 child = child->next;
4368 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004369 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004370 child = child->next;
4371 }
4372 if (subtype != NULL)
4373 type->subtypes = subtype;
4374 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004375 }
4376 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004377 xmlSchemaPErr2(ctxt, node, child,
4378 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
4379 "ComplexType %s has unexpected content\n",
4380 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004382 if (type->attributeWildcard != NULL)
4383 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillard4255d502002-04-16 15:50:10 +00004384 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00004385 return (type);
4386}
4387
Daniel Veillard4255d502002-04-16 15:50:10 +00004388/**
4389 * xmlSchemaParseSchema:
4390 * @ctxt: a schema validation context
4391 * @node: a subtree containing XML Schema informations
4392 *
4393 * parse a XML schema definition from a node set
4394 * *WARNING* this interface is highly subject to change
4395 *
4396 * Returns the internal XML Schema structure built from the resource or
4397 * NULL in case of error
4398 */
4399static xmlSchemaPtr
4400xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4401{
4402 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004403 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004404 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004405 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004406
4407 if ((ctxt == NULL) || (node == NULL))
4408 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004409
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004410 nberrors = ctxt->nberrors;
4411 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004412 if (IS_SCHEMA(node, "schema")) {
4413 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414 if (schema == NULL)
4415 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004416 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
4417 if (val != NULL) {
4418 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
4419 } else {
4420 schema->targetNamespace = NULL;
4421 }
4422 schema->id = xmlSchemaGetProp(ctxt, node, "id");
4423 schema->version = xmlSchemaGetProp(ctxt, node, "version");
4424 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004425 if (val != NULL) {
4426 if (xmlStrEqual(val, BAD_CAST "qualified"))
4427 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
4428 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4429 xmlSchemaPErr2(ctxt, node, child,
4430 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
4431 "Invalid value %s for elementFormDefault\n",
4432 val, NULL);
4433 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004434 } else {
4435 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
4436 }
4437 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004438 if (val != NULL) {
4439 if (xmlStrEqual(val, BAD_CAST "qualified"))
4440 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
4441 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4442 xmlSchemaPErr2(ctxt, node, child,
4443 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
4444 "Invalid value %s for attributeFormDefault\n",
4445 val, NULL);
4446 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004447 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004448
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004449 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
4450 } else {
4451 xmlDocPtr doc;
4452
4453 doc = node->doc;
4454
4455 if ((doc != NULL) && (doc->URL != NULL)) {
4456 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4457 XML_SCHEMAP_NOT_SCHEMA,
4458 "File %s is not a schemas", doc->URL, NULL);
4459 } else {
4460 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4461 XML_SCHEMAP_NOT_SCHEMA,
4462 "File is not a schemas", NULL, NULL);
4463 }
4464 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004465 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004466 if (ctxt->nberrors != 0) {
4467 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004468 xmlSchemaFree(schema);
4469 schema = NULL;
4470 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004471 }
4472 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004473#ifdef DEBUG
4474 if (schema == NULL)
4475 xmlGenericError(xmlGenericErrorContext,
4476 "xmlSchemaParse() failed\n");
4477#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004478 return (schema);
4479}
4480
4481/************************************************************************
4482 * *
4483 * Validating using Schemas *
4484 * *
4485 ************************************************************************/
4486
4487/************************************************************************
4488 * *
4489 * Reading/Writing Schemas *
4490 * *
4491 ************************************************************************/
4492
4493/**
4494 * xmlSchemaNewParserCtxt:
4495 * @URL: the location of the schema
4496 *
4497 * Create an XML Schemas parse context for that file/resource expected
4498 * to contain an XML Schemas file.
4499 *
4500 * Returns the parser context or NULL in case of error
4501 */
4502xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004503xmlSchemaNewParserCtxt(const char *URL)
4504{
Daniel Veillard4255d502002-04-16 15:50:10 +00004505 xmlSchemaParserCtxtPtr ret;
4506
4507 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004508 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004509
4510 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4511 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004512 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4513 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004514 return (NULL);
4515 }
4516 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004517 ret->dict = xmlDictCreate();
4518 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004519 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004520 return (ret);
4521}
4522
4523/**
Daniel Veillard6045c902002-10-09 21:13:59 +00004524 * xmlSchemaNewMemParserCtxt:
4525 * @buffer: a pointer to a char array containing the schemas
4526 * @size: the size of the array
4527 *
4528 * Create an XML Schemas parse context for that memory buffer expected
4529 * to contain an XML Schemas file.
4530 *
4531 * Returns the parser context or NULL in case of error
4532 */
4533xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004534xmlSchemaNewMemParserCtxt(const char *buffer, int size)
4535{
Daniel Veillard6045c902002-10-09 21:13:59 +00004536 xmlSchemaParserCtxtPtr ret;
4537
4538 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004539 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00004540
4541 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4542 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004543 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4544 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00004545 return (NULL);
4546 }
4547 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4548 ret->buffer = buffer;
4549 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00004550 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00004551 return (ret);
4552}
4553
4554/**
Daniel Veillard9d751502003-10-29 13:21:47 +00004555 * xmlSchemaNewDocParserCtxt:
4556 * @doc: a preparsed document tree
4557 *
4558 * Create an XML Schemas parse context for that document.
4559 * NB. The document may be modified during the parsing process.
4560 *
4561 * Returns the parser context or NULL in case of error
4562 */
4563xmlSchemaParserCtxtPtr
4564xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
4565{
4566 xmlSchemaParserCtxtPtr ret;
4567
4568 if (doc == NULL)
4569 return (NULL);
4570
4571 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4572 if (ret == NULL) {
4573 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
4574 NULL);
4575 return (NULL);
4576 }
4577 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4578 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00004579 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00004580 /* The application has responsibility for the document */
4581 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00004582
4583 return (ret);
4584}
4585
4586/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004587 * xmlSchemaFreeParserCtxt:
4588 * @ctxt: the schema parser context
4589 *
4590 * Free the resources associated to the schema parser context
4591 */
4592void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004593xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
4594{
Daniel Veillard4255d502002-04-16 15:50:10 +00004595 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004596 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004597 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004598 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004599 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004600 xmlFree(ctxt);
4601}
4602
4603/************************************************************************
4604 * *
4605 * Building the content models *
4606 * *
4607 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004608
Daniel Veillard4255d502002-04-16 15:50:10 +00004609/**
4610 * xmlSchemaBuildAContentModel:
4611 * @type: the schema type definition
4612 * @ctxt: the schema parser context
4613 * @name: the element name whose content is being built
4614 *
4615 * Generate the automata sequence needed for that type
4616 */
4617static void
4618xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004619 xmlSchemaParserCtxtPtr ctxt,
4620 const xmlChar * name)
4621{
Daniel Veillard4255d502002-04-16 15:50:10 +00004622 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004623 xmlGenericError(xmlGenericErrorContext,
4624 "Found unexpected type = NULL in %s content model\n",
4625 name);
4626 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004627 }
4628 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004629 case XML_SCHEMA_TYPE_ANY:
4630 /* TODO : handle the namespace too */
4631 /* TODO : make that a specific transition type */
4632 TODO ctxt->state =
4633 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
4634 BAD_CAST "*", NULL);
4635 break;
4636 case XML_SCHEMA_TYPE_ELEMENT:{
4637 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00004638
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004639 /* TODO : handle the namespace too */
4640 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004641
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004642 if (elem->maxOccurs >= UNBOUNDED) {
4643 if (elem->minOccurs > 1) {
4644 xmlAutomataStatePtr tmp;
4645 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00004646
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004647 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4648 oldstate,
4649 NULL);
4650 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004651
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004652 counter = xmlAutomataNewCounter(ctxt->am,
4653 elem->minOccurs -
4654 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00004655
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004656 if (elem->refDecl != NULL) {
4657 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4658 elem->refDecl,
4659 ctxt,
4660 elem->refDecl->
4661 name);
4662 } else {
4663 ctxt->state =
4664 xmlAutomataNewTransition(ctxt->am,
4665 ctxt->state, NULL,
4666 elem->name, type);
4667 }
4668 tmp = ctxt->state;
4669 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4670 counter);
4671 ctxt->state =
4672 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4673 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00004674
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004675 } else {
4676 if (elem->refDecl != NULL) {
4677 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4678 elem->refDecl,
4679 ctxt,
4680 elem->refDecl->
4681 name);
4682 } else {
4683 ctxt->state =
4684 xmlAutomataNewTransition(ctxt->am,
4685 ctxt->state, NULL,
4686 elem->name, type);
4687 }
4688 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4689 oldstate);
4690 if (elem->minOccurs == 0) {
4691 /* basically an elem* */
4692 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4693 ctxt->state);
4694 }
4695 }
4696 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
4697 xmlAutomataStatePtr tmp;
4698 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00004699
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004700 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4701 oldstate, NULL);
4702 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004703
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004704 counter = xmlAutomataNewCounter(ctxt->am,
4705 elem->minOccurs - 1,
4706 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004707
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004708 if (elem->refDecl != NULL) {
4709 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4710 elem->refDecl, ctxt,
4711 elem->refDecl->name);
4712 } else {
4713 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4714 ctxt->state,
4715 NULL,
4716 elem->name,
4717 type);
4718 }
4719 tmp = ctxt->state;
4720 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4721 counter);
4722 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
4723 NULL,
4724 counter);
4725 if (elem->minOccurs == 0) {
4726 /* basically an elem? */
4727 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4728 ctxt->state);
4729 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00004730
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004731 } else {
4732 if (elem->refDecl != NULL) {
4733 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4734 elem->refDecl, ctxt,
4735 elem->refDecl->name);
4736 } else {
4737 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4738 ctxt->state,
4739 NULL,
4740 elem->name,
4741 type);
4742 }
4743 if (elem->minOccurs == 0) {
4744 /* basically an elem? */
4745 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4746 ctxt->state);
4747 }
4748 }
4749 break;
4750 }
4751 case XML_SCHEMA_TYPE_SEQUENCE:{
4752 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004753
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004754 /*
4755 * If max and min occurances are default (1) then
4756 * simply iterate over the subtypes
4757 */
4758 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4759 subtypes = type->subtypes;
4760 while (subtypes != NULL) {
4761 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4762 subtypes = subtypes->next;
4763 }
4764 } else {
4765 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004766
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004767 if (type->maxOccurs >= UNBOUNDED) {
4768 if (type->minOccurs > 1) {
4769 xmlAutomataStatePtr tmp;
4770 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004771
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004772 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4773 oldstate,
4774 NULL);
4775 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004776
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004777 counter = xmlAutomataNewCounter(ctxt->am,
4778 type->
4779 minOccurs - 1,
4780 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004781
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004782 subtypes = type->subtypes;
4783 while (subtypes != NULL) {
4784 xmlSchemaBuildAContentModel(subtypes, ctxt,
4785 name);
4786 subtypes = subtypes->next;
4787 }
4788 tmp = ctxt->state;
4789 xmlAutomataNewCountedTrans(ctxt->am, tmp,
4790 oldstate, counter);
4791 ctxt->state =
4792 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4793 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004794
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004795 } else {
4796 subtypes = type->subtypes;
4797 while (subtypes != NULL) {
4798 xmlSchemaBuildAContentModel(subtypes, ctxt,
4799 name);
4800 subtypes = subtypes->next;
4801 }
4802 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4803 oldstate);
4804 if (type->minOccurs == 0) {
4805 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4806 ctxt->state);
4807 }
4808 }
4809 } else if ((type->maxOccurs > 1)
4810 || (type->minOccurs > 1)) {
4811 xmlAutomataStatePtr tmp;
4812 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004813
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004814 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4815 oldstate,
4816 NULL);
4817 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00004818
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004819 counter = xmlAutomataNewCounter(ctxt->am,
4820 type->minOccurs -
4821 1,
4822 type->maxOccurs -
4823 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004824
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004825 subtypes = type->subtypes;
4826 while (subtypes != NULL) {
4827 xmlSchemaBuildAContentModel(subtypes, ctxt,
4828 name);
4829 subtypes = subtypes->next;
4830 }
4831 tmp = ctxt->state;
4832 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4833 counter);
4834 ctxt->state =
4835 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4836 counter);
4837 if (type->minOccurs == 0) {
4838 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4839 ctxt->state);
4840 }
Daniel Veillardb509f152002-04-17 16:28:10 +00004841
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004842 } else {
4843 subtypes = type->subtypes;
4844 while (subtypes != NULL) {
4845 xmlSchemaBuildAContentModel(subtypes, ctxt,
4846 name);
4847 subtypes = subtypes->next;
4848 }
4849 if (type->minOccurs == 0) {
4850 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4851 ctxt->state);
4852 }
4853 }
4854 }
4855 break;
4856 }
4857 case XML_SCHEMA_TYPE_CHOICE:{
4858 xmlSchemaTypePtr subtypes;
4859 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00004860
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004861 start = ctxt->state;
4862 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00004863
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004864 /*
4865 * iterate over the subtypes and remerge the end with an
4866 * epsilon transition
4867 */
4868 if (type->maxOccurs == 1) {
4869 subtypes = type->subtypes;
4870 while (subtypes != NULL) {
4871 ctxt->state = start;
4872 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4873 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4874 subtypes = subtypes->next;
4875 }
4876 } else {
4877 int counter;
4878 xmlAutomataStatePtr hop;
4879 int maxOccurs = type->maxOccurs == UNBOUNDED ?
4880 UNBOUNDED : type->maxOccurs - 1;
4881 int minOccurs =
4882 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00004883
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004884 /*
4885 * use a counter to keep track of the number of transtions
4886 * which went through the choice.
4887 */
4888 counter =
4889 xmlAutomataNewCounter(ctxt->am, minOccurs,
4890 maxOccurs);
4891 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00004892
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004893 subtypes = type->subtypes;
4894 while (subtypes != NULL) {
4895 ctxt->state = start;
4896 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4897 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4898 subtypes = subtypes->next;
4899 }
4900 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4901 counter);
4902 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4903 counter);
4904 }
4905 if (type->minOccurs == 0) {
4906 xmlAutomataNewEpsilon(ctxt->am, start, end);
4907 }
4908 ctxt->state = end;
4909 break;
4910 }
4911 case XML_SCHEMA_TYPE_ALL:{
4912 xmlAutomataStatePtr start;
4913 xmlSchemaTypePtr subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +00004914 /*
4915 * Changed, since type in not an xmlSchemaElement here.
4916 */
4917 /* xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type; */
4918 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004919 int lax;
4920
4921 subtypes = type->subtypes;
4922 if (subtypes == NULL)
4923 break;
4924 start = ctxt->state;
4925 while (subtypes != NULL) {
4926 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00004927 /*
4928 * the following 'if' was needed to fix bug 139897
4929 * not quite sure why it only needs to be done for
4930 * elements with a 'ref', but it seems to work ok.
4931 */
4932 if (subtypes->ref != NULL)
4933 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
William M. Bracke7091952004-05-11 15:09:58 +00004934 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004935 /* TODO : handle the namespace too */
4936 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4937 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4938 ctxt->state, elem->name, 1,
4939 1, subtypes);
4940 } else {
4941 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4942 ctxt->state, elem->name,
4943 elem->minOccurs,
4944 elem->maxOccurs,
4945 subtypes);
4946 }
4947 subtypes = subtypes->next;
4948 }
4949 lax = type->minOccurs == 0;
4950 ctxt->state =
4951 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4952 lax);
4953 break;
4954 }
4955 case XML_SCHEMA_TYPE_RESTRICTION:
4956 if (type->subtypes != NULL)
4957 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4958 break;
4959 case XML_SCHEMA_TYPE_EXTENSION:
4960 if (type->baseType != NULL) {
4961 xmlSchemaTypePtr subtypes;
4962
Daniel Veillardf7627552004-04-22 07:15:40 +00004963 if (type->recurse) {
4964 xmlSchemaPErr(ctxt, type->node,
4965 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4966 "Schemas: extension type %s is recursive\n",
4967 type->name, NULL);
4968 return;
4969 }
4970 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004971 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00004972 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004973 subtypes = type->subtypes;
4974 while (subtypes != NULL) {
4975 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4976 subtypes = subtypes->next;
4977 }
4978 } else if (type->subtypes != NULL)
4979 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4980 break;
4981 case XML_SCHEMA_TYPE_GROUP:
4982 if (type->subtypes == NULL) {
William M. Brack29aa7722004-05-12 00:27:56 +00004983 xmlSchemaTypePtr rgroup;
4984 if (type->ref != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004985 rgroup = xmlSchemaGetGroup(ctxt->schema, type->ref,
William M. Brack29aa7722004-05-12 00:27:56 +00004986 type->refNs);
4987 if (rgroup == NULL) {
4988 xmlSchemaPErr(ctxt, type->node,
4989 XML_SCHEMAP_UNKNOWN_REF,
4990 "Schemas: group %s reference %s is not found",
4991 name, type->ref);
4992 return;
4993 }
4994 xmlSchemaBuildAContentModel(rgroup, ctxt, name);
4995 break;
4996 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004997 }
4998 case XML_SCHEMA_TYPE_COMPLEX:
4999 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5000 if (type->subtypes != NULL)
5001 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
5002 break;
5003 default:
5004 xmlGenericError(xmlGenericErrorContext,
5005 "Found unexpected type %d in %s content model\n",
5006 type->type, name);
5007 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005008 }
5009}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005010
Daniel Veillard4255d502002-04-16 15:50:10 +00005011/**
5012 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005013 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00005014 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005015 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00005016 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005017 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00005018 */
5019static void
5020xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005021 xmlSchemaParserCtxtPtr ctxt,
5022 const xmlChar * name)
5023{
Daniel Veillard4255d502002-04-16 15:50:10 +00005024 xmlAutomataStatePtr start;
5025
Daniel Veillard4255d502002-04-16 15:50:10 +00005026 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005027 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00005028 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005029 elem->contentType = XML_SCHEMA_CONTENT_ANY;
5030 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00005031 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005032 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005033 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005034 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
5035 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005036 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005037
5038#ifdef DEBUG_CONTENT
5039 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005040 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005041#endif
5042
Daniel Veillard4255d502002-04-16 15:50:10 +00005043 ctxt->am = xmlNewAutomata();
5044 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005045 xmlGenericError(xmlGenericErrorContext,
5046 "Cannot create automata for elem %s\n", name);
5047 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005048 }
5049 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
5050 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
5051 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00005052 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005053 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005054 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
5055 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005056 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005057 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
5058 "Content model of %s is not determinist:\n", name,
5059 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00005060 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00005061#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005062 xmlGenericError(xmlGenericErrorContext,
5063 "Content model of %s:\n", name);
5064 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005065#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00005066 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005067 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005068 xmlFreeAutomata(ctxt->am);
5069 ctxt->am = NULL;
5070}
5071
5072/**
5073 * xmlSchemaRefFixupCallback:
5074 * @elem: the schema element context
5075 * @ctxt: the schema parser context
5076 *
5077 * Free the resources associated to the schema parser context
5078 */
5079static void
5080xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005081 xmlSchemaParserCtxtPtr ctxt,
5082 const xmlChar * name,
5083 const xmlChar * context ATTRIBUTE_UNUSED,
5084 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005085{
5086 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005087 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00005088
Daniel Veillard4255d502002-04-16 15:50:10 +00005089 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005090 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005091
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005092 if (elem->subtypes != NULL) {
5093 xmlSchemaPErr(ctxt, elem->node,
5094 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
Daniel Veillard3646d642004-06-02 19:19:14 +00005095 "Schemas: element %s has both ref and subtype\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005096 name, NULL);
5097 return;
5098 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005099 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005100
5101 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005102 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
5103 "Schemas: element %s ref to %s not found\n",
5104 name, elem->ref);
5105 return;
5106 }
5107 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005108 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005109 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005110
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005111 if (elem->subtypes != NULL) {
5112 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
Daniel Veillard3646d642004-06-02 19:19:14 +00005113 "Schemas: element %s has both type and subtype\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005114 name, NULL);
5115 return;
5116 }
5117 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
5118 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00005119
5120 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005121 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
5122 "Schemas: element %s type %s not found\n", name,
5123 elem->namedType);
5124 return;
5125 }
5126 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005127 }
5128}
5129
William M. Bracke7091952004-05-11 15:09:58 +00005130/**
5131 * xmlSchemaParseListRefFixup:
5132 * @type: the schema type definition
5133 * @ctxt: the schema parser context
5134 *
5135 * Fixup of the itemType reference of the list type.
5136 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00005137static void
William M. Bracke7091952004-05-11 15:09:58 +00005138xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
5139{
5140 const xmlChar *itemType, *namespace;
5141 xmlSchemaTypePtr subtype;
5142
5143 /* Handle the "itemType" attribute. */
William M. Brack29aa7722004-05-12 00:27:56 +00005144 itemType = xmlGetQNameProp(ctxt, type->node, "itemType", &namespace);
William M. Bracke7091952004-05-11 15:09:58 +00005145 if (itemType != NULL) {
5146 /* Do not allow more that one item type. */
5147 if (type->subtypes != NULL) {
5148 xmlSchemaPErr(ctxt, type->node,
5149 XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE,
5150 "List %s has more than one item type defined\n",
5151 type->name, NULL);
5152 }
5153 subtype = xmlSchemaGetType(ctxt->schema, itemType, namespace);
5154 if (subtype == NULL) {
5155 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_TYPE,
5156 "List %s references an unknown item type: %s\n",
5157 type->name, xmlSchemaGetProp(ctxt, type->node,
William M. Brack29aa7722004-05-12 00:27:56 +00005158 "itemType"));
William M. Bracke7091952004-05-11 15:09:58 +00005159 } else
5160 type->subtypes = subtype;
5161 }
5162}
5163
5164/**
5165 * xmlSchemaParseUnionRefCheck:
5166 * @typeDecl: the schema type definition
5167 * @ctxt: the schema parser context
5168 *
5169 * Checks the memberTypes references of the union type.
5170 */
5171static void
5172xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00005173 xmlSchemaParserCtxtPtr ctxt)
5174{
5175 const xmlChar *cur, *end, *prefix, *ncName, *namespace;
5176 xmlChar *tmp;
5177 xmlSchemaTypePtr subtype;
5178 xmlNsPtr ns;
5179 int len;
5180
William M. Bracke7091952004-05-11 15:09:58 +00005181 if ((type->type != XML_SCHEMA_TYPE_UNION) || (type->ref == NULL))
Daniel Veillard377e1a92004-04-16 16:30:05 +00005182 return;
5183
William M. Bracke7091952004-05-11 15:09:58 +00005184 cur = type->ref;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005185 do {
5186 while (IS_BLANK_CH(*cur))
5187 cur++;
5188 end = cur;
5189 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5190 end++;
5191 if (end == cur)
5192 break;
5193 tmp = xmlStrndup(cur, end - cur);
5194 ncName = xmlSplitQName3(tmp, &len);
5195 if (ncName != NULL) {
5196 prefix = xmlDictLookup(ctxt->dict, tmp, len);
5197 } else {
5198 prefix = NULL;
5199 ncName = tmp;
5200 }
William M. Bracke7091952004-05-11 15:09:58 +00005201 ns = xmlSearchNs(type->node->doc, type->node, prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005202 if (ns == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005203 if (prefix != NULL) {
5204 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_PREFIX_UNDEFINED,
5205 "Union %s: the namespace prefix of member type "
5206 "%s is undefined\n",
5207 type->name, (const xmlChar *) tmp);
5208 }
5209 namespace = NULL;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005210 } else {
5211 namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
5212 }
5213 /* Lookup the referenced type */
5214 subtype = xmlSchemaGetType(ctxt->schema, ncName, namespace);
5215 if (subtype == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005216 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
5217 "Union %s references an unknown member type %s\n",
5218 type->name, (const xmlChar *) tmp);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005219 }
William M. Bracke7091952004-05-11 15:09:58 +00005220 xmlFree(tmp);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005221 cur = end;
William M. Bracke7091952004-05-11 15:09:58 +00005222 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005223}
5224
Daniel Veillard4255d502002-04-16 15:50:10 +00005225/**
Daniel Veillard3646d642004-06-02 19:19:14 +00005226 * xmlSchemaGetOnymousTypeName:
5227 * @attr: the attribute declaration/use
5228 *
5229 * Returns the name of the attribute; if the attribute
5230 * is a reference, the name of the referenced global type will be returned.
5231 */
5232static const xmlChar *
5233xmlSchemaGetOnymousAttrName(xmlSchemaAttributePtr attr)
5234{
5235 if (attr->ref != NULL)
5236 return(attr->ref);
5237 else
5238 return(attr->name);
5239}
5240
5241/**
5242 * xmlSchemaGetOnymousTargetNsURI:
5243 * @type: the type (element or attribute)
5244 *
5245 * Returns the target namespace URI of the type; if the type is a reference,
5246 * the target namespace of the referenced type will be returned.
5247 */
5248static const xmlChar *
5249xmlSchemaGetOnymousTargetNsURI(xmlSchemaTypePtr type)
5250{
5251 if (type->type == XML_SCHEMA_TYPE_ELEMENT) {
5252 if (type->ref != NULL)
5253 return(((xmlSchemaElementPtr)((xmlSchemaElementPtr)
5254 type)->subtypes)->targetNamespace);
5255 else
5256 return(((xmlSchemaElementPtr) type)->targetNamespace);
5257 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
5258 if (type->ref != NULL)
5259 return(((xmlSchemaAttributePtr)((xmlSchemaAttributePtr)
5260 type)->subtypes)->targetNamespace);
5261 else
5262 return(((xmlSchemaAttributePtr) type)->targetNamespace);
5263 } else
5264 return (NULL);
5265}
5266
5267/**
5268 * xmlSchemaIsDerivedFromBuiltInType:
5269 * @ctxt: the schema parser context
5270 * @type: the type definition
5271 * @valType: the value type
5272 *
5273 *
5274 * Returns 1 if the type has the given value type, or
5275 * is derived from such a type.
5276 */
5277int
5278xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
5279 xmlSchemaTypePtr type, int valType)
5280{
5281 /* TODO: Check if this works in every case. */
5282 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
5283 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
5284 if (type->flags == valType)
5285 return(1);
5286 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
5287 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
5288 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
5289 ((xmlSchemaAttributePtr) type)->subtypes, valType));
5290 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
5291 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
5292 if (type->baseType != NULL)
5293 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
5294 valType));
5295 } else if ((type->subtypes != NULL) &&
5296 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
5297 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
5298 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
5299 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
5300 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
5301 valType));
5302 }
5303
5304 return (0);
5305}
5306
5307/**
5308 * xmlSchemaBuildAttributeUsesOwned:
5309 * @ctxt: the schema parser context
5310 * @type: the complex type definition
5311 * @cur: the attribute declaration list
5312 * @lastUse: the top of the attribute use list
5313 *
5314 * Builds the attribute uses list on the given complex type.
5315 * This one is supposed to be called by
5316 * xmlSchemaBuildAttributeValidation only.
5317 */
5318static int
5319xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
5320 xmlSchemaAttributePtr cur,
5321 xmlSchemaAttributeLinkPtr *uses,
5322 xmlSchemaAttributeLinkPtr *lastUse)
5323{
5324 xmlSchemaAttributeLinkPtr tmp;
5325 while (cur != NULL) {
5326 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5327 /*
5328 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
5329 * to by the ·actual value·s of the ref [attribute] of the
5330 * <attributeGroup> [children], if any."
5331 */
5332 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
5333 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
5334 lastUse) == -1) {
5335 return (-1);
5336 }
5337 } else {
5338 /* W3C: "1 The set of attribute uses corresponding to the
5339 * <attribute> [children], if any."
5340 */
5341 tmp = (xmlSchemaAttributeLinkPtr)
5342 xmlMalloc(sizeof(xmlSchemaAttributeLink));
5343 if (tmp == NULL) {
5344 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
5345 return (-1);
5346 }
5347 tmp->attr = cur;
5348 tmp->next = NULL;
5349 if (*uses == NULL)
5350 *uses = tmp;
5351 else
5352 (*lastUse)->next = tmp;
5353 *lastUse = tmp;
5354 }
5355 cur = cur->next;
5356 }
5357 return (0);
5358}
5359
5360static int
5361xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
5362 xmlSchemaWildcardPtr *dest,
5363 xmlSchemaWildcardPtr source)
5364{
5365 xmlSchemaWildcardNsPtr cur, tmp, last;
5366
5367 if ((source == NULL) || (*dest == NULL))
5368 return(-1);
5369 (*dest)->any = source->any;
5370 cur = source->nsSet;
5371 last = NULL;
5372 while (cur != NULL) {
5373 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5374 if (tmp == NULL)
5375 return(-1);
5376 tmp->value = cur->value;
5377 if (last == NULL)
5378 (*dest)->nsSet = tmp;
5379 else
5380 last->next = tmp;
5381 last = tmp;
5382 cur = cur->next;
5383 }
5384 if ((*dest)->negNsSet != NULL)
5385 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
5386 if (source->negNsSet != NULL) {
5387 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5388 if ((*dest)->negNsSet == NULL)
5389 return(-1);
5390 (*dest)->negNsSet->value = source->negNsSet->value;
5391 } else
5392 (*dest)->negNsSet = NULL;
5393 return(0);
5394}
5395
5396static int
5397xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
5398 xmlSchemaWildcardPtr completeWild,
5399 xmlSchemaWildcardPtr curWild)
5400{
5401 xmlSchemaWildcardNsPtr cur, curB, tmp;
5402
5403 /*
5404 * 1 If O1 and O2 are the same value, then that value must be the
5405 * value.
5406 */
5407 if ((completeWild->any == curWild->any) &&
5408 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
5409 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
5410
5411 if ((completeWild->negNsSet == NULL) ||
5412 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
5413
5414 if (completeWild->nsSet != NULL) {
5415 int found;
5416
5417 /*
5418 * Check equality of sets.
5419 */
5420 cur = completeWild->nsSet;
5421 while (cur != NULL) {
5422 found = 0;
5423 curB = curWild->nsSet;
5424 while (curB != NULL) {
5425 if (cur->value == curB->value) {
5426 found = 1;
5427 break;
5428 }
5429 curB = curB->next;
5430 }
5431 if (!found)
5432 break;
5433 cur = cur->next;
5434 }
5435 if (found)
5436 return(0);
5437 } else
5438 return(0);
5439 }
5440 }
5441 /*
5442 * 2 If either O1 or O2 is any, then any must be the value
5443 */
5444 if ((completeWild->any != curWild->any) && (completeWild->any)) {
5445 if (completeWild->any == 0) {
5446 completeWild->any = 1;
5447 if (completeWild->nsSet != NULL) {
5448 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5449 completeWild->nsSet = NULL;
5450 }
5451 if (completeWild->negNsSet != NULL) {
5452 xmlFree(completeWild->negNsSet);
5453 completeWild->negNsSet = NULL;
5454 }
5455 }
5456 }
5457 /*
5458 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
5459 * then the union of those sets must be the value.
5460 */
5461 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
5462 int found;
5463 xmlSchemaWildcardNsPtr start;
5464
5465 cur = curWild->nsSet;
5466 start = completeWild->nsSet;
5467 while (cur != NULL) {
5468 found = 0;
5469 curB = start;
5470 while (curB != NULL) {
5471 if (cur->value == curB->value) {
5472 found = 1;
5473 break;
5474 }
5475 curB = curB->next;
5476 }
5477 if (!found) {
5478 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5479 if (tmp == NULL)
5480 return (-1);
5481 tmp->value = cur->value;
5482 tmp->next = completeWild->nsSet;
5483 completeWild->nsSet = tmp;
5484 }
5485 cur = cur->next;
5486 }
5487
5488 return(0);
5489 }
5490 /*
5491 * 4 If the two are negations of different values (namespace names
5492 * or ·absent·), then a pair of not and ·absent· must be the value.
5493 */
5494 if ((completeWild->negNsSet != NULL) &&
5495 (curWild->negNsSet != NULL) &&
5496 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
5497 completeWild->negNsSet->value = NULL;
5498 }
5499 /*
5500 * 5.
5501 */
5502 if (((completeWild->negNsSet != NULL) &&
5503 (completeWild->negNsSet->value != NULL) &&
5504 (curWild->nsSet != NULL)) ||
5505 ((curWild->negNsSet != NULL) &&
5506 (curWild->negNsSet->value != NULL) &&
5507 (completeWild->nsSet != NULL))) {
5508
5509 int nsFound, absentFound = 0;
5510
5511 if (completeWild->nsSet != NULL) {
5512 cur = completeWild->nsSet;
5513 curB = curWild->negNsSet;
5514 } else {
5515 cur = curWild->nsSet;
5516 curB = completeWild->negNsSet;
5517 }
5518 nsFound = 0;
5519 while (cur != NULL) {
5520 if (cur->value == NULL)
5521 absentFound = 1;
5522 else if (cur->value == curB->value)
5523 nsFound = 1;
5524 if (nsFound && absentFound)
5525 break;
5526 cur = cur->next;
5527 }
5528
5529 if (nsFound && absentFound) {
5530 /*
5531 * 5.1 If the set S includes both the negated namespace
5532 * name and ·absent·, then any must be the value.
5533 */
5534 completeWild->any = 1;
5535 if (completeWild->nsSet != NULL) {
5536 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5537 completeWild->nsSet = NULL;
5538 }
5539 if (completeWild->negNsSet != NULL) {
5540 xmlFree(completeWild->negNsSet);
5541 completeWild->negNsSet = NULL;
5542 }
5543 } else if (nsFound && (!absentFound)) {
5544 /*
5545 * 5.2 If the set S includes the negated namespace name
5546 * but not ·absent·, then a pair of not and ·absent· must
5547 * be the value.
5548 */
5549 if (completeWild->nsSet != NULL) {
5550 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5551 completeWild->nsSet = NULL;
5552 }
5553 if (completeWild->negNsSet == NULL) {
5554 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5555 if (completeWild->negNsSet == NULL)
5556 return (-1);
5557 }
5558 completeWild->negNsSet->value = NULL;
5559 } else if ((!nsFound) && absentFound) {
5560 /*
5561 * 5.3 If the set S includes ·absent· but not the negated
5562 * namespace name, then the union is not expressible.
5563 */
5564 xmlSchemaPErr(ctxt, completeWild->node,
5565 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
5566 "The union of the wilcard is not expressible\n",
5567 NULL, NULL);
5568 return(0);
5569 } else if ((!nsFound) && (!absentFound)) {
5570 /*
5571 * 5.4 If the set S does not include either the negated namespace
5572 * name or ·absent·, then whichever of O1 or O2 is a pair of not
5573 * and a namespace name must be the value.
5574 */
5575 if (completeWild->negNsSet == NULL) {
5576 if (completeWild->nsSet != NULL) {
5577 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5578 completeWild->nsSet = NULL;
5579 }
5580 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5581 if (completeWild->negNsSet == NULL)
5582 return (-1);
5583 completeWild->negNsSet->value = curWild->negNsSet->value;
5584 }
5585 }
5586 return (0);
5587 }
5588 /*
5589 * 6.
5590 */
5591 if (((completeWild->negNsSet != NULL) &&
5592 (completeWild->negNsSet->value == NULL) &&
5593 (curWild->nsSet != NULL)) ||
5594 ((curWild->negNsSet != NULL) &&
5595 (curWild->negNsSet->value == NULL) &&
5596 (completeWild->nsSet != NULL))) {
5597
5598 if (completeWild->nsSet != NULL) {
5599 cur = completeWild->nsSet;
5600 } else {
5601 cur = curWild->nsSet;
5602 }
5603 while (cur != NULL) {
5604 if (cur->value == NULL) {
5605 /*
5606 * 6.1 If the set S includes ·absent·, then any must be the
5607 * value.
5608 */
5609 completeWild->any = 1;
5610 if (completeWild->nsSet != NULL) {
5611 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5612 completeWild->nsSet = NULL;
5613 }
5614 if (completeWild->negNsSet != NULL) {
5615 xmlFree(completeWild->negNsSet);
5616 completeWild->negNsSet = NULL;
5617 }
5618 return (0);
5619 }
5620 cur = cur->next;
5621 }
5622 if (completeWild->negNsSet == NULL) {
5623 /*
5624 * 6.2 If the set S does not include ·absent·, then a pair of not
5625 * and ·absent· must be the value.
5626 */
5627 if (completeWild->nsSet != NULL) {
5628 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5629 completeWild->nsSet = NULL;
5630 }
5631 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5632 if (completeWild->negNsSet == NULL)
5633 return (-1);
5634 completeWild->negNsSet->value = NULL;
5635 }
5636 return (0);
5637 }
5638 return (0);
5639
5640}
5641
5642static int
5643xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
5644 xmlSchemaWildcardPtr completeWild,
5645 xmlSchemaWildcardPtr curWild)
5646{
5647 xmlSchemaWildcardNsPtr cur, curB, prev, last = NULL, tmp;
5648
5649 /*
5650 * 1 If O1 and O2 are the same value, then that value must be the
5651 * value.
5652 */
5653 if ((completeWild->any == curWild->any) &&
5654 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
5655 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
5656
5657 if ((completeWild->negNsSet == NULL) ||
5658 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
5659
5660 if (completeWild->nsSet != NULL) {
5661 int found;
5662
5663 /*
5664 * Check equality of sets.
5665 */
5666 cur = completeWild->nsSet;
5667 while (cur != NULL) {
5668 found = 0;
5669 curB = curWild->nsSet;
5670 while (curB != NULL) {
5671 if (cur->value == curB->value) {
5672 found = 1;
5673 break;
5674 }
5675 curB = curB->next;
5676 }
5677 if (!found)
5678 break;
5679 cur = cur->next;
5680 }
5681 if (found)
5682 return(0);
5683 } else
5684 return(0);
5685 }
5686 }
5687 /*
5688 * 2 If either O1 or O2 is any, then the other must be the value.
5689 */
5690 if ((completeWild->any != curWild->any) && (completeWild->any)) {
5691 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
5692 return(-1);
5693 return(0);
5694 }
5695 /*
5696 * 3 If either O1 or O2 is a pair of not and a value (a namespace
5697 * name or ·absent·) and the other is a set of (namespace names or
5698 * ·absent·), then that set, minus the negated value if it was in
5699 * the set, minus ·absent· if it was in the set, must be the value.
5700 */
5701 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
5702 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
5703 const xmlChar *neg;
5704
5705 if (completeWild->nsSet == NULL) {
5706 neg = completeWild->negNsSet->value;
5707 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
5708 return(-1);
5709 } else
5710 neg = curWild->negNsSet->value;
5711 /*
5712 * Remove absent and negated.
5713 */
5714 prev = NULL;
5715 cur = completeWild->nsSet;
5716 while (cur != NULL) {
5717 if (cur->value == NULL) {
5718 if (prev == NULL)
5719 completeWild->nsSet = cur->next;
5720 else
5721 prev->next = cur->next;
5722 xmlFree(cur);
5723 break;
5724 }
5725 prev = cur;
5726 cur = cur->next;
5727 }
5728 if (neg != NULL) {
5729 prev = NULL;
5730 cur = completeWild->nsSet;
5731 while (cur != NULL) {
5732 if (cur->value == neg) {
5733 if (prev == NULL)
5734 completeWild->nsSet = cur->next;
5735 else
5736 prev->next = cur->next;
5737 xmlFree(cur);
5738 break;
5739 }
5740 prev = cur;
5741 cur = cur->next;
5742 }
5743 }
5744
5745 return(0);
5746 }
5747 /*
5748 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
5749 * then the intersection of those sets must be the value.
5750 */
5751 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
5752 int found;
5753
5754 cur = completeWild->nsSet;
5755 prev = NULL;
5756 while (cur != NULL) {
5757 found = 0;
5758 curB = curWild->nsSet;
5759 while (curB != NULL) {
5760 if (cur->value == curB->value) {
5761 found = 1;
5762 break;
5763 }
5764 curB = curB->next;
5765 }
5766 if (!found) {
5767 if (prev == NULL)
5768 completeWild->nsSet = cur->next;
5769 else
5770 prev->next = cur->next;
5771 tmp = cur->next;
5772 xmlFree(cur);
5773 cur = tmp;
5774 continue;
5775 }
5776 prev = cur;
5777 cur = cur->next;
5778 }
5779
5780 return(0);
5781 }
5782 /* 5 If the two are negations of different namespace names,
5783 * then the intersection is not expressible
5784 */
5785 if ((completeWild->negNsSet != NULL) &&
5786 (curWild->negNsSet != NULL) &&
5787 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
5788 (completeWild->negNsSet->value != NULL) &&
5789 (curWild->negNsSet->value != NULL)) {
5790
5791 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
5792 "The intersection of the wilcard is not expressible\n",
5793 NULL, NULL);
5794 return(0);
5795 }
5796 /*
5797 * 6 If the one is a negation of a namespace name and the other
5798 * is a negation of ·absent·, then the one which is the negation
5799 * of a namespace name must be the value.
5800 */
5801 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
5802 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
5803 (completeWild->negNsSet->value == NULL)) {
5804 completeWild->negNsSet->value = curWild->negNsSet->value;
5805 }
5806 return(0);
5807}
5808
5809
5810static xmlSchemaWildcardPtr
5811xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
5812 xmlSchemaAttributePtr attrs,
5813 xmlSchemaWildcardPtr completeWild)
5814{
5815 while (attrs != NULL) {
5816 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5817 xmlSchemaAttributeGroupPtr group;
5818
5819 group = (xmlSchemaAttributeGroupPtr) attrs;
5820 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
5821 if (group->attributes != NULL) {
5822 if (group->attributeWildcard != NULL)
5823 xmlSchemaBuildCompleteAttributeWildcard(ctxt,
5824 group->attributes, group->attributeWildcard);
5825 else
5826 group->attributeWildcard =
5827 xmlSchemaBuildCompleteAttributeWildcard(ctxt,
5828 group->attributes, group->attributeWildcard);
5829 }
5830 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
5831 }
5832 if (group->attributeWildcard != NULL) {
5833 if (completeWild == NULL) {
5834 /*
5835 * Copy the first encountered wildcard as context, except for the annotation.
5836 */
5837 completeWild = xmlSchemaAddWildcard(ctxt);
5838 completeWild->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
5839 if (!xmlSchemaCloneWildcardNsConstraints(ctxt,
5840 &completeWild, group->attributeWildcard))
5841 return(NULL);
5842 completeWild->processContents = group->attributeWildcard->processContents;
5843 /*
5844 * Although the complete wildcard might not correspond to any
5845 * node in the schema, we will save this context node.
5846 */
5847 completeWild->node = group->attributeWildcard->node;
5848 return(completeWild);
5849 }
5850 if (xmlSchemaIntersectWildcards(ctxt, completeWild, group->attributeWildcard) == -1) {
5851 xmlSchemaFreeWildcard(completeWild);
5852 return(NULL);
5853 }
5854 }
5855 }
5856 attrs = attrs->next;
5857 }
5858
5859 return (completeWild);
5860}
5861
5862/**
5863 * xmlSchemaMatchesWildcardNs:
5864 * @wild: the wildcard
5865 * @ns: the namespace
5866 *
5867 *
5868 * Returns 1 if the given namespace matches the wildcard,
5869 * 0 otherwise.
5870 */
5871static int
5872xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
5873{
5874 if (wild == NULL)
5875 return(0);
5876
5877 if (wild->any)
5878 return(1);
5879 else if (wild->nsSet != NULL) {
5880 xmlSchemaWildcardNsPtr cur;
5881
5882 cur = wild->nsSet;
5883 while (cur != NULL) {
5884 if (xmlStrEqual(cur->value, ns))
5885 return(1);
5886 cur = cur->next;
5887 }
5888 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
5889 (!xmlStrEqual(wild->negNsSet->value, ns)))
5890 return(1);
5891
5892 return(0);
5893}
5894
5895/**
5896 * xmlSchemaBuildAttributeValidation:
5897 * @ctxt: the schema parser context
5898 * @type: the complex type definition
5899 *
5900 *
5901 * Builds the wildcard and the attribute uses on the given complex type.
5902 * Returns -1 if an internal error occurs, 0 otherwise.
5903 */
5904static int
5905xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
5906{
5907 xmlSchemaTypePtr baseType = NULL;
5908 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
5909 lastUse = NULL, lastBaseUse;
5910 xmlSchemaAttributePtr attrs;
5911 int baseIsAnyType = 0;
5912
5913 /*
5914 * Complex Type Definition with complex content Schema Component.
5915 *
5916 * Attribute uses.
5917 */
5918 if (type->attributeUses != NULL) {
5919 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5920 "Internal error: xmlSchemaParseBuildAttributeUses: "
5921 "attribute uses already builded.\n",
5922 NULL, NULL);
5923 return (-1);
5924 }
5925 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) ||
5926 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
5927 /*
5928 * Inherit the attribute uses of the base type.
5929 */
5930 baseType = type->subtypes->subtypes->baseType;
5931 /*
5932 * TODO: URGENT: This is not nice, but currently
5933 * xmlSchemaTypeAnyTypeDef is static in xmlschematypes.c.
5934 */
5935 if ((baseType->type == XML_SCHEMA_TYPE_BASIC) &&
5936 xmlStrEqual(baseType->name, "anyType")) {
5937 baseIsAnyType = 1;
5938 }
5939 /*
5940 * TODO: Does the spec state that it is an error to "extend" the
5941 * anyType?
5942 */
5943 if (!baseIsAnyType) {
5944 if (baseType != NULL) {
5945 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
5946 tmp = (xmlSchemaAttributeLinkPtr)
5947 xmlMalloc(sizeof(xmlSchemaAttributeLink));
5948 if (tmp == NULL) {
5949 xmlSchemaPErrMemory(ctxt,
5950 "building attribute uses of complexType", NULL);
5951 return (-1);
5952 }
5953 tmp->attr = cur->attr;
5954 tmp->next = NULL;
5955 if (type->attributeUses == NULL) {
5956 type->attributeUses = tmp;
5957 } else
5958 lastBaseUse->next = tmp;
5959 lastBaseUse = tmp;
5960 }
5961 }
5962 }
5963 attrs = type->subtypes->subtypes->attributes;
5964 /*
5965 * Handle attribute wildcards.
5966 */
5967 type->attributeWildcard =
5968 xmlSchemaBuildCompleteAttributeWildcard(ctxt,
5969 attrs,
5970 type->subtypes->subtypes->attributeWildcard);
5971 if ((type->attributeWildcard != NULL) &&
5972 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard))
5973 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
5974
5975 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
5976 (baseType != NULL) && (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
5977 (baseType->attributeWildcard != NULL)) {
5978 if (type->attributeWildcard != NULL) {
5979 /*
5980 * Union the complete wildcard with the base wildcard.
5981 */
5982 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
5983 baseType->attributeWildcard) == -1)
5984 return (-1);
5985 } else {
5986 /*
5987 * Just inherit the wildcard.
5988 */
5989 type->attributeWildcard = baseType->attributeWildcard;
5990 }
5991 }
5992 } else {
5993 /*
5994 * Although the complexType is implicitely derived by "restriction"
5995 * from the ur-type, this is not (yet?) reflected by libxml2.
5996 */
5997 baseType = NULL;
5998 attrs = type->attributes;
5999 if (attrs != NULL)
6000 type->attributeWildcard =
6001 xmlSchemaBuildCompleteAttributeWildcard(ctxt, attrs, type->attributeWildcard);
6002 }
6003 /*
6004 * Gather attribute uses defined by this type.
6005 */
6006 if (attrs != NULL) {
6007 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
6008 &uses, &lastUse) == -1) {
6009 return (-1);
6010 }
6011 }
6012 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
6013 * "Two distinct attribute declarations in the {attribute uses} must
6014 * not have identical {name}s and {target namespace}s."
6015 *
6016 * For "extension" this is done further down.
6017 */
6018 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
6019 cur = uses;
6020 while (cur != NULL) {
6021 tmp = cur->next;
6022 while (tmp != NULL) {
6023 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6024 xmlSchemaGetOnymousAttrName(tmp->attr))) &&
6025 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
6026 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
6027
6028 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
6029 "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
6030 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6031 break;
6032 }
6033 tmp = tmp->next;
6034 }
6035 cur = cur->next;
6036 }
6037 }
6038 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
6039 /*
6040 * Derive by restriction.
6041 */
6042 if (baseIsAnyType) {
6043 type->attributeUses = uses;
6044 } else {
6045 int found;
6046
6047 cur = uses;
6048 while (cur != NULL) {
6049 found = 0;
6050 base = type->attributeUses;
6051 while (base != NULL) {
6052 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6053 xmlSchemaGetOnymousAttrName(base->attr))) &&
6054 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr),
6055 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) base->attr)))) {
6056
6057 found = 1;
6058 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6059 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6060 /*
6061 * derivation-ok-restriction 2.1.1
6062 */
6063 xmlSchemaPErr(ctxt, cur->attr->node,
6064 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
6065 "derivation-ok-restriction.2.1.1: "
6066 "The \"optional\" attribute "
6067 "use \"%s\" is inconsistent with a matching "
6068 "\"required\" attribute use of the base type\n",
6069 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6070 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
6071 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6072 /*
6073 * derivation-ok-restriction 3
6074 */
6075 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
6076 "derivation-ok-restriction.3: "
6077 "The \"required\" attribute use \"%s\" of the base type "
6078 "does not have a matching attribute use in the derived type\n",
6079 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6080
6081 } else {
6082 /*
6083 * Override the attribute use.
6084 */
6085 base->attr = cur->attr;
6086 }
6087 /*
6088 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
6089 */
6090 break;
6091 }
6092 base = base->next;
6093 }
6094
6095 if (!found) {
6096 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6097 /*
6098 * derivation-ok-restriction 2.2
6099 */
6100 if ((type->attributeWildcard != NULL) &&
6101 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
6102 cur->attr->targetNamespace))
6103 found = 1;
6104
6105 if (!found) {
6106 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
6107 "derivation-ok-restriction.2.2: "
6108 "The attribute use \"%s\" has neither a matching attribute use, "
6109 "nor a matching wildcard in the base type\n",
6110 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6111 } else {
6112 /*
6113 * Add the attribute use.
6114 *
6115 * Note that this may lead to funny derivation error reports, if
6116 * multiple equal attribute uses exist; but this is not
6117 * allowed anyway, and it will be reported beforehand.
6118 */
6119 tmp = cur;
6120 if (prev != NULL)
6121 prev->next = cur->next;
6122 else
6123 uses = cur->next;
6124 cur = cur->next;
6125 if (type->attributeUses == NULL) {
6126 type->attributeUses = tmp;
6127 } else
6128 lastBaseUse->next = tmp;
6129 lastBaseUse = tmp;
6130
6131 continue;
6132 }
6133 }
6134 }
6135 prev = cur;
6136 cur = cur->next;
6137 }
6138 if (uses != NULL)
6139 xmlSchemaFreeAttributeUseList(uses);
6140 }
6141 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
6142 /*
6143 * The spec allows only appending, and not other kinds of extensions.
6144 *
6145 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
6146 */
6147 if (uses != NULL) {
6148 if (type->attributeUses == NULL) {
6149 type->attributeUses = uses;
6150 } else
6151 lastBaseUse->next = uses;
6152 }
6153 } else {
6154 /*
6155 * Derive implicitely from the ur-type.
6156 */
6157 type->attributeUses = uses;
6158}
6159 /*
6160 * 3.4.6 -> Complex Type Definition Properties Correct
6161 */
6162 if (type->attributeUses != NULL) {
6163 cur = type->attributeUses;
6164 prev = NULL;
6165 while (cur != NULL) {
6166 /*
6167 * 4. Two distinct attribute declarations in the {attribute uses} must
6168 * not have identical {name}s and {target namespace}s.
6169 *
6170 * Note that this was already done for "restriction" and types derived from
6171 * the ur-type.
6172 */
6173 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
6174 tmp = cur->next;
6175 while (tmp != NULL) {
6176 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6177 xmlSchemaGetOnymousAttrName(tmp->attr))) &&
6178 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
6179 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
6180
6181 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
6182 "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
6183 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6184 break;
6185 }
6186 tmp = tmp->next;
6187 }
6188 }
6189 /*
6190 * 5. Two distinct attribute declarations in the {attribute uses} must
6191 * not have {type definition}s which are or are derived from ID.
6192 */
6193 if ((cur->attr->subtypes != NULL) &&
6194 /*
6195 * TODO: FIXME: XML_SCHEMAS_ID should be used instead of "23" !!!,
6196 * but the xmlSchemaValType is not made public yet.
6197 */
6198 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, 23))) {
6199 if (id != NULL) {
6200 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_5,
6201 "ct-props-correct.5: Two attribute declarations, "
6202 "\"%s\" and \"%s\" have types which derived from ID\n",
6203 xmlSchemaGetOnymousAttrName(id->attr),
6204 xmlSchemaGetOnymousAttrName(cur->attr));
6205 }
6206 id = cur;
6207 }
6208 /*
6209 * Remove "prohibited" attribute uses. The reason this is done at this late
6210 * stage is to be able to catch dublicate attribute uses. So we had to keep
6211 * prohibited uses in the list as well.
6212 */
6213 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6214 tmp = cur;
6215 if (prev == NULL)
6216 type->attributeUses = cur->next;
6217 else
6218 prev->next = cur->next;
6219 cur = cur->next;
6220 xmlFree(tmp);
6221 } else {
6222 prev = cur;
6223 cur = cur->next;
6224 }
6225 }
6226 }
6227 /*
6228 * TODO: This check should be removed if we are 100% sure of
6229 * the base type attribute uses already being built.
6230 */
6231 if ((baseType != NULL) && (!baseIsAnyType) &&
6232 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
6233 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
6234 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAS_ERR_INTERNAL,
6235 "Internal error: xmlSchemaParseBuildAttributeUses: "
6236 "attribute uses not builded on base type \"%s\".\n",
6237 baseType->name, NULL);
6238 }
6239 return (0);
6240}
6241
6242/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006243 * xmlSchemaTypeFixup:
6244 * @typeDecl: the schema type definition
6245 * @ctxt: the schema parser context
6246 *
6247 * Fixes the content model of the type.
6248 */
6249static void
6250xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006251 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00006252{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006253 if (typeDecl == NULL)
6254 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006255 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006256 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006257 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006258 switch (typeDecl->type) {
6259 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
6260 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
6261 if (typeDecl->subtypes != NULL)
6262 typeDecl->contentType =
6263 typeDecl->subtypes->contentType;
6264 break;
6265 }
6266 case XML_SCHEMA_TYPE_RESTRICTION:{
6267 if (typeDecl->subtypes != NULL)
6268 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006269
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006270 if (typeDecl->base != NULL) {
6271 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00006272
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006273 baseType =
6274 xmlSchemaGetType(ctxt->schema, typeDecl->base,
6275 typeDecl->baseNs);
6276 if (baseType == NULL) {
6277 xmlSchemaPErr(ctxt, typeDecl->node,
6278 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00006279 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006280 name, typeDecl->base);
Daniel Veillard3646d642004-06-02 19:19:14 +00006281 } else if (baseType->contentType ==
6282 XML_SCHEMA_CONTENT_UNKNOWN) {
6283 /*
6284 * The base type might be not "type fixed" yet,
6285 * so do it now. */
6286 /*
6287 * TODO: Is a check for circular derivation already
6288 * done?
6289 */
6290 xmlSchemaTypeFixup(baseType, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006291 }
6292 typeDecl->baseType = baseType;
6293 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006294 if (typeDecl->subtypes == NULL)
William M. Bracke7091952004-05-11 15:09:58 +00006295 if (typeDecl->baseType != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006296 typeDecl->contentType =
6297 typeDecl->baseType->contentType;
William M. Bracke7091952004-05-11 15:09:58 +00006298 } else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006299 /* 1.1.1 */
6300 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006301 else if ((typeDecl->subtypes->subtypes == NULL) &&
6302 ((typeDecl->subtypes->type ==
6303 XML_SCHEMA_TYPE_ALL)
6304 || (typeDecl->subtypes->type ==
6305 XML_SCHEMA_TYPE_SEQUENCE)))
6306 /* 1.1.2 */
6307 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
6308 else if ((typeDecl->subtypes->type ==
6309 XML_SCHEMA_TYPE_CHOICE)
6310 && (typeDecl->subtypes->subtypes == NULL))
6311 /* 1.1.3 */
6312 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
6313 else {
6314 /* 1.2 and 2.X are applied at the other layer */
6315 typeDecl->contentType =
6316 XML_SCHEMA_CONTENT_ELEMENTS;
6317 }
6318 break;
6319 }
6320 case XML_SCHEMA_TYPE_EXTENSION:{
6321 xmlSchemaContentType explicitContentType;
6322 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00006323
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006324 if (typeDecl->base != NULL) {
6325 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00006326
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006327 baseType =
6328 xmlSchemaGetType(ctxt->schema, typeDecl->base,
6329 typeDecl->baseNs);
6330 if (baseType == NULL) {
6331 xmlSchemaPErr(ctxt, typeDecl->node,
6332 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00006333 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006334 name, typeDecl->base);
Daniel Veillard3646d642004-06-02 19:19:14 +00006335 } else if (baseType->contentType ==
6336 XML_SCHEMA_CONTENT_UNKNOWN) {
6337 /*
6338 * The base type might be not "type fixed" yet,
6339 * so do it now. */
6340 /*
6341 * TODO: Is a check for circular derivation already
6342 * done?
6343 */
6344 xmlSchemaTypeFixup(baseType, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006345 }
6346 typeDecl->baseType = baseType;
6347 }
6348 if (typeDecl->subtypes != NULL)
6349 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006350
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006351 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
6352 if (typeDecl->subtypes == NULL)
6353 /* 1.1.1 */
6354 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
6355 else if ((typeDecl->subtypes->subtypes == NULL) &&
6356 ((typeDecl->subtypes->type ==
6357 XML_SCHEMA_TYPE_ALL)
6358 || (typeDecl->subtypes->type ==
6359 XML_SCHEMA_TYPE_SEQUENCE)))
6360 /* 1.1.2 */
6361 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
6362 else if ((typeDecl->subtypes->type ==
6363 XML_SCHEMA_TYPE_CHOICE)
6364 && (typeDecl->subtypes->subtypes == NULL))
6365 /* 1.1.3 */
6366 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00006367
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006368 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
6369 typeDecl->baseNs);
6370 if (base == NULL) {
6371 xmlSchemaPErr(ctxt, typeDecl->node,
6372 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
6373 "Schemas: base type %s of type %s not found\n",
6374 typeDecl->base, name);
6375 return;
6376 }
Daniel Veillard2582a332004-04-18 19:49:46 +00006377 if (typeDecl->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006378 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillard2582a332004-04-18 19:49:46 +00006379 xmlSchemaPErr(ctxt, typeDecl->node,
6380 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
6381 "Schemas: extension type %s is recursive\n",
6382 name, NULL);
6383 return;
6384 }
6385 typeDecl->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006386 xmlSchemaTypeFixup(base, ctxt, NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +00006387 typeDecl->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006388 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
6389 /* 2.1 */
6390 typeDecl->contentType = base->contentType;
6391 } else if (base->contentType ==
6392 XML_SCHEMA_CONTENT_EMPTY) {
6393 /* 2.2 imbitable ! */
6394 typeDecl->contentType =
6395 XML_SCHEMA_CONTENT_ELEMENTS;
6396 } else {
6397 /* 2.3 imbitable pareil ! */
6398 typeDecl->contentType =
6399 XML_SCHEMA_CONTENT_ELEMENTS;
6400 }
6401 break;
6402 }
6403 case XML_SCHEMA_TYPE_COMPLEX:{
6404 if (typeDecl->subtypes == NULL) {
6405 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00006406
6407 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
6408 typeDecl->contentType =
6409 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006410 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00006411 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006412 typeDecl->contentType =
6413 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +00006414 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006415 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
6416 NULL);
6417 if (typeDecl->subtypes != NULL)
6418 typeDecl->contentType =
6419 typeDecl->subtypes->contentType;
6420 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006421 /* Evaluate the derivation method. */
6422 if ((typeDecl->subtypes != NULL) &&
6423 ((typeDecl->subtypes->type ==
6424 XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
6425 (typeDecl->subtypes->type ==
6426 XML_SCHEMA_TYPE_SIMPLE_CONTENT)) &&
6427 (typeDecl->subtypes->subtypes != NULL)) {
6428 if (typeDecl->subtypes->subtypes->type ==
6429 XML_SCHEMA_TYPE_EXTENSION) {
6430 typeDecl->flags |=
6431 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
6432 } else if (typeDecl->subtypes->subtypes->type ==
6433 XML_SCHEMA_TYPE_RESTRICTION) {
6434 typeDecl->flags |=
6435 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006436 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006437 }
6438 }
6439 xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006440 break;
6441 }
6442 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
6443 if (typeDecl->subtypes == NULL) {
6444 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00006445 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
6446 typeDecl->contentType =
6447 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006448 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00006449 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006450 typeDecl->contentType =
6451 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +00006452 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006453 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
6454 NULL);
6455 if (typeDecl->subtypes != NULL)
6456 typeDecl->contentType =
6457 typeDecl->subtypes->contentType;
6458 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006459 /*
6460 * Removed due to implementation of the build of attribute uses.
6461 */
6462 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00006463 if (typeDecl->attributes == NULL)
6464 typeDecl->attributes =
6465 typeDecl->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +00006466 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006467 }
6468 break;
6469 }
6470 case XML_SCHEMA_TYPE_SEQUENCE:
6471 case XML_SCHEMA_TYPE_GROUP:
6472 case XML_SCHEMA_TYPE_ALL:
6473 case XML_SCHEMA_TYPE_CHOICE:
6474 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
6475 break;
Daniel Veillard3646d642004-06-02 19:19:14 +00006476 case XML_SCHEMA_TYPE_LIST:
6477 xmlSchemaParseListRefFixup(typeDecl, ctxt);
6478 /* no break on purpose */
6479 case XML_SCHEMA_TYPE_UNION:
6480 if (typeDecl->type == XML_SCHEMA_TYPE_UNION)
6481 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
6482 /* no break on purpose */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006483 case XML_SCHEMA_TYPE_BASIC:
6484 case XML_SCHEMA_TYPE_ANY:
6485 case XML_SCHEMA_TYPE_FACET:
6486 case XML_SCHEMA_TYPE_SIMPLE:
6487 case XML_SCHEMA_TYPE_UR:
6488 case XML_SCHEMA_TYPE_ELEMENT:
6489 case XML_SCHEMA_TYPE_ATTRIBUTE:
6490 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +00006491 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006492 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006493 case XML_SCHEMA_FACET_MININCLUSIVE:
6494 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6495 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6496 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
6497 case XML_SCHEMA_FACET_TOTALDIGITS:
6498 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6499 case XML_SCHEMA_FACET_PATTERN:
6500 case XML_SCHEMA_FACET_ENUMERATION:
6501 case XML_SCHEMA_FACET_WHITESPACE:
6502 case XML_SCHEMA_FACET_LENGTH:
6503 case XML_SCHEMA_FACET_MAXLENGTH:
6504 case XML_SCHEMA_FACET_MINLENGTH:
6505 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006506 if (typeDecl->subtypes != NULL)
6507 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006508 break;
6509 }
6510 }
Daniel Veillard8651f532002-04-17 09:06:27 +00006511#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006512 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006513 xmlGenericError(xmlGenericErrorContext,
6514 "Type of %s : %s:%d :", name,
6515 typeDecl->node->doc->URL,
6516 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006517 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006518 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006519 }
Daniel Veillard8651f532002-04-17 09:06:27 +00006520 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006521 case XML_SCHEMA_CONTENT_SIMPLE:
6522 xmlGenericError(xmlGenericErrorContext, "simple\n");
6523 break;
6524 case XML_SCHEMA_CONTENT_ELEMENTS:
6525 xmlGenericError(xmlGenericErrorContext, "elements\n");
6526 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006527 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006528 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
6529 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006530 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006531 xmlGenericError(xmlGenericErrorContext, "empty\n");
6532 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006533 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006534 xmlGenericError(xmlGenericErrorContext, "mixed\n");
6535 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006536 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006537 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
6538 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006539 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006540 xmlGenericError(xmlGenericErrorContext, "basic\n");
6541 break;
6542 default:
6543 xmlGenericError(xmlGenericErrorContext,
6544 "not registered !!!\n");
6545 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006546 }
6547#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00006548}
6549
6550/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006551 * xmlSchemaCheckFacet:
6552 * @facet: the facet
6553 * @typeDecl: the schema type definition
6554 * @ctxt: the schema parser context or NULL
6555 * @name: name of the type
6556 *
6557 * Checks the default values types, especially for facets
6558 *
6559 * Returns 0 if okay or -1 in cae of error
6560 */
6561int
6562xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006563 xmlSchemaTypePtr typeDecl,
6564 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006565{
6566 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
6567 int ret = 0;
6568
6569 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006570 nonNegativeIntegerType =
6571 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
6572 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006573 }
6574 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006575 case XML_SCHEMA_FACET_MININCLUSIVE:
6576 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6577 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6578 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
6579 /*
6580 * Okay we need to validate the value
6581 * at that point.
6582 */
6583 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006584
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006585 vctxt = xmlSchemaNewValidCtxt(NULL);
6586 if (vctxt == NULL)
6587 break;
6588 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
6589 facet->value);
6590 facet->val = vctxt->value;
6591 vctxt->value = NULL;
6592 if (facet->val == NULL) {
6593 /* error code */
6594 if (ctxt != NULL) {
6595 xmlSchemaPErr(ctxt, facet->node,
6596 XML_SCHEMAP_INVALID_FACET,
6597 "Schemas: type %s facet value %s invalid\n",
6598 name, facet->value);
6599 }
6600 ret = -1;
6601 }
6602 xmlSchemaFreeValidCtxt(vctxt);
6603 break;
6604 }
6605 case XML_SCHEMA_FACET_ENUMERATION:{
6606 /*
6607 * Okay we need to validate the value
6608 * at that point.
6609 */
6610 xmlSchemaValidCtxtPtr vctxt;
6611 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006612
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006613 vctxt = xmlSchemaNewValidCtxt(NULL);
6614 if (vctxt == NULL)
6615 break;
6616 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
6617 facet->value);
6618 if (tmp != 0) {
6619 if (ctxt != NULL) {
6620 xmlSchemaPErr(ctxt, facet->node,
6621 XML_SCHEMAP_INVALID_ENUM,
6622 "Schemas: type %s enumeration value %s invalid\n",
6623 name, facet->value);
6624 }
6625 ret = -1;
6626 }
6627 xmlSchemaFreeValidCtxt(vctxt);
6628 break;
6629 }
6630 case XML_SCHEMA_FACET_PATTERN:
6631 facet->regexp = xmlRegexpCompile(facet->value);
6632 if (facet->regexp == NULL) {
6633 xmlSchemaPErr(ctxt, typeDecl->node,
6634 XML_SCHEMAP_REGEXP_INVALID,
6635 "Schemas: type %s facet regexp %s invalid\n",
6636 name, facet->value);
6637 ret = -1;
6638 }
6639 break;
6640 case XML_SCHEMA_FACET_TOTALDIGITS:
6641 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6642 case XML_SCHEMA_FACET_LENGTH:
6643 case XML_SCHEMA_FACET_MAXLENGTH:
6644 case XML_SCHEMA_FACET_MINLENGTH:{
6645 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006646
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006647 tmp =
6648 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
6649 facet->value,
6650 &facet->val);
6651 if (tmp != 0) {
6652 /* error code */
6653 if (ctxt != NULL) {
6654 xmlSchemaPErr(ctxt, facet->node,
6655 XML_SCHEMAP_INVALID_FACET_VALUE,
6656 "Schemas: type %s facet value %s invalid\n",
6657 name, facet->value);
6658 }
6659 ret = -1;
6660 }
6661 break;
6662 }
6663 case XML_SCHEMA_FACET_WHITESPACE:{
6664 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
6665 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
6666 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
6667 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
6668 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
6669 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
6670 } else {
6671 if (ctxt != NULL) {
6672 xmlSchemaPErr(ctxt, facet->node,
6673 XML_SCHEMAP_INVALID_WHITE_SPACE,
6674 "Schemas: type %s whiteSpace value %s invalid\n",
6675 name, facet->value);
6676 }
6677 ret = -1;
6678 }
6679 }
6680 default:
6681 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006682 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006683 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006684}
6685
6686/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006687 * xmlSchemaCheckDefaults:
6688 * @typeDecl: the schema type definition
6689 * @ctxt: the schema parser context
6690 *
6691 * Checks the default values types, especially for facets
6692 */
6693static void
6694xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006695 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00006696{
Daniel Veillard4255d502002-04-16 15:50:10 +00006697 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006698 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006699 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006700 if (typeDecl->facets != NULL) {
6701 xmlSchemaFacetPtr facet = typeDecl->facets;
6702
6703 while (facet != NULL) {
6704 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
6705 facet = facet->next;
6706 }
6707 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006708 }
6709}
6710
6711/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00006712 * xmlSchemaAttrGrpFixup:
6713 * @attrgrpDecl: the schema attribute definition
6714 * @ctxt: the schema parser context
6715 * @name: the attribute name
6716 *
6717 * Fixes finish doing the computations on the attributes definitions
6718 */
6719static void
Daniel Veillard3646d642004-06-02 19:19:14 +00006720xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006721 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00006722{
6723 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00006724 name = attrgrp->name;
6725 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006726 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00006727 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006728 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006729
Daniel Veillard3646d642004-06-02 19:19:14 +00006730 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref, attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006731 if (ref == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006732 xmlSchemaPErr(ctxt, attrgrp->node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006733 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
6734 "Schemas: attribute group %s reference %s not found\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00006735 name, attrgrp->ref);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006736 return;
6737 }
6738 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00006739 attrgrp->attributes = ref->attributes;
6740 attrgrp->attributeWildcard = ref->attributeWildcard;
6741 }
6742 /*
6743 * Removed, since a global attribute group does not need to hold any
6744 * attributes or wildcard
6745 */
6746 /*
6747 else {
6748 xmlSchemaPErr(ctxt, attrgrp->node, XML_SCHEMAP_NOATTR_NOREF,
6749 "Schemas: attribute group %s has no attributes nor reference\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006750 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00006751 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006752 */
Daniel Veillard13e04c62002-04-23 17:51:29 +00006753}
6754
6755/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006756 * xmlSchemaAttrFixup:
6757 * @attrDecl: the schema attribute definition
6758 * @ctxt: the schema parser context
6759 * @name: the attribute name
6760 *
6761 * Fixes finish doing the computations on the attributes definitions
6762 */
6763static void
6764xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006765 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00006766{
6767 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006768 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006769 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006770 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006771 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006772 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006773
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006774 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
6775 attrDecl->typeNs);
6776 if (type == NULL) {
6777 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
6778 "Schemas: attribute %s type %s not found\n",
6779 name, attrDecl->typeName);
6780 }
6781 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006782 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006783 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00006784
Daniel Veillard3646d642004-06-02 19:19:14 +00006785 ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006786 if (ref == NULL) {
6787 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
6788 "Schemas: attribute %s reference %s not found\n",
6789 name, attrDecl->ref);
6790 return;
6791 }
6792 xmlSchemaAttrFixup(ref, ctxt, NULL);
6793 attrDecl->subtypes = ref->subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +00006794 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006795 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
6796 "Schemas: attribute %s has no type nor reference\n",
6797 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006798 }
6799}
6800
6801/**
6802 * xmlSchemaParse:
6803 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00006804 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00006805 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00006806 * XML Shema struture which can be used to validate instances.
6807 * *WARNING* this interface is highly subject to change
6808 *
6809 * Returns the internal XML Schema structure built from the resource or
6810 * NULL in case of error
6811 */
6812xmlSchemaPtr
6813xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
6814{
6815 xmlSchemaPtr ret = NULL;
6816 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006817 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00006818 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00006819 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006820
6821 xmlSchemaInitTypes();
6822
Daniel Veillard6045c902002-10-09 21:13:59 +00006823 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00006824 return (NULL);
6825
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00006826 nberrors = ctxt->nberrors;
6827 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006828 ctxt->counter = 0;
6829 ctxt->container = NULL;
6830
6831 /*
6832 * First step is to parse the input document into an DOM/Infoset
6833 */
Daniel Veillard6045c902002-10-09 21:13:59 +00006834 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006835 doc = xmlReadFile((const char *) ctxt->URL, NULL,
6836 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006837 if (doc == NULL) {
6838 xmlSchemaPErr(ctxt, NULL,
6839 XML_SCHEMAP_FAILED_LOAD,
6840 "xmlSchemaParse: could not load %s\n",
6841 ctxt->URL, NULL);
6842 return (NULL);
6843 }
Daniel Veillard6045c902002-10-09 21:13:59 +00006844 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006845 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
6846 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006847 if (doc == NULL) {
6848 xmlSchemaPErr(ctxt, NULL,
6849 XML_SCHEMAP_FAILED_PARSE,
6850 "xmlSchemaParse: could not parse\n",
6851 NULL, NULL);
6852 return (NULL);
6853 }
6854 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00006855 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00006856 } else if (ctxt->doc != NULL) {
6857 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00006858 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00006859 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006860 xmlSchemaPErr(ctxt, NULL,
6861 XML_SCHEMAP_NOTHING_TO_PARSE,
6862 "xmlSchemaParse: could not parse\n",
6863 NULL, NULL);
6864 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006865 }
6866
6867 /*
6868 * Then extract the root and Schema parse it
6869 */
6870 root = xmlDocGetRootElement(doc);
6871 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006872 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
6873 XML_SCHEMAP_NOROOT,
6874 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00006875 if (!preserve) {
6876 xmlFreeDoc(doc);
6877 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006878 return (NULL);
6879 }
6880
6881 /*
6882 * Remove all the blank text nodes
6883 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006884 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00006885
6886 /*
6887 * Then do the parsing for good
6888 */
6889 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00006890 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00006891 if (!preserve) {
6892 xmlFreeDoc(doc);
6893 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006894 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00006895 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006896 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00006897 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00006898
6899 /*
6900 * Then fix all the references.
6901 */
6902 ctxt->schema = ret;
6903 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006904 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006905
6906 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00006907 * Then fixup all attributes declarations
6908 */
6909 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
6910
6911 /*
6912 * Then fixup all attributes group declarations
6913 */
6914 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
6915 ctxt);
6916
6917 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00006918 * Then fixup all types properties
6919 */
6920 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
6921
6922 /*
6923 * Then build the content model for all elements
6924 */
6925 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006926 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006927
6928 /*
6929 * Then check the defaults part of the type like facets values
6930 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006931 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
6932 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006933
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00006934 if (ctxt->nberrors != 0) {
6935 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006936 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00006937 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006938 return (ret);
6939}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006940
Daniel Veillard4255d502002-04-16 15:50:10 +00006941/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00006942 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00006943 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00006944 * @err: the error callback
6945 * @warn: the warning callback
6946 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00006947 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00006948 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00006949 */
6950void
6951xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006952 xmlSchemaValidityErrorFunc err,
6953 xmlSchemaValidityWarningFunc warn, void *ctx)
6954{
Daniel Veillard4255d502002-04-16 15:50:10 +00006955 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006956 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006957 ctxt->error = err;
6958 ctxt->warning = warn;
6959 ctxt->userData = ctx;
6960}
6961
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006962/**
6963 * xmlSchemaFacetTypeToString:
6964 * @type: the facet type
6965 *
6966 * Convert the xmlSchemaTypeType to a char string.
6967 *
6968 * Returns the char string representation of the facet type if the
6969 * type is a facet and an "Internal Error" string otherwise.
6970 */
6971static const char *
6972xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
6973{
6974 switch (type) {
6975 case XML_SCHEMA_FACET_PATTERN:
6976 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006977 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006978 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006979 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006980 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006981 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006982 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006983 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006984 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006985 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006986 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006987 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006988 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006989 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006990 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006991 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006992 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006993 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006994 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006995 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006996 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006997 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006998 return ("fractionDigits");
6999 default:
7000 break;
7001 }
7002 return ("Internal Error");
7003}
7004
7005/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00007006 * xmlSchemaValidateFacetsInternal:
7007 * @ctxt: a schema validation context
7008 * @base: the base type
7009 * @facets: the list of facets to check
7010 * @value: the lexical repr of the value to validate
7011 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +00007012 * @fireErrors: if 0, only internal errors will be fired;
7013 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00007014 *
7015 * Check a value against all facet conditions
7016 *
7017 * Returns 0 if the element is schemas valid, a positive error code
7018 * number otherwise and -1 in case of internal or API error.
7019 */
7020static int
7021xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
7022 xmlSchemaTypePtr base,
William M. Bracke7091952004-05-11 15:09:58 +00007023 xmlSchemaFacetPtr facets,
7024 const xmlChar * value, int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00007025{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007026 int ret = 0;
7027 int tmp = 0;
7028 xmlSchemaTypeType type;
7029 xmlSchemaFacetPtr facet = facets;
7030
7031 while (facet != NULL) {
7032 type = facet->type;
7033 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007034 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007035
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007036 while (facet != NULL) {
7037 tmp =
7038 xmlSchemaValidateFacet(base, facet, value,
7039 ctxt->value);
7040 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007041 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007042 }
7043 facet = facet->next;
7044 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007045 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007046 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007047
7048 if (tmp != 0) {
7049 ret = tmp;
Daniel Veillard377e1a92004-04-16 16:30:05 +00007050 if (fireErrors)
William M. Bracke7091952004-05-11 15:09:58 +00007051 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET,
7052 "Failed to validate type with facet %s\n",
7053 (const xmlChar *) xmlSchemaFacetTypeToString(type),
7054 NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007055 }
7056 if (facet != NULL)
7057 facet = facet->next;
7058 }
7059 return (ret);
7060}
7061
William M. Brack87640d52004-04-17 14:58:15 +00007062/**
7063 * xmlSchemaValidateFacets:
7064 * @ctxt: a schema validation context
7065 * @base: the base type
7066 * @facets: the list of facets to check
7067 * @value: the lexical repr of the value to validate
7068 * @val: the precomputed value
7069 *
7070 * Check a value against all facet conditions
7071 *
7072 * Returns 0 if the element is schemas valid, a positive error code
7073 * number otherwise and -1 in case of internal or API error.
7074 */
7075static int
7076xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
7077 xmlSchemaTypePtr base,
7078 xmlSchemaFacetPtr facets, const xmlChar * value)
7079{
7080 return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
7081}
7082
Daniel Veillard4255d502002-04-16 15:50:10 +00007083/************************************************************************
7084 * *
7085 * Simple type validation *
7086 * *
7087 ************************************************************************/
7088
7089/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00007090 * xmlSchemaValidateSimpleValueUnion:
7091 * @ctxt: a schema validation context
7092 * @type: the type declaration
7093 * @value: the value to validate
7094 *
7095 * Validates a value against a union.
7096 *
7097 * Returns 0 if the value is valid, a positive error code
7098 * number otherwise and -1 in case of internal or API error.
7099 */
7100static int
7101xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
7102 xmlSchemaTypePtr type, const xmlChar * value)
7103{
7104 int ret = 0;
7105 const xmlChar *cur, *end, *prefix, *ncName;
7106 xmlChar *tmp;
7107 xmlSchemaTypePtr subtype;
7108 xmlNsPtr ns;
7109 int len;
7110
7111
7112 /* Process referenced memberTypes. */
7113 cur = type->ref;
7114 do {
7115 while (IS_BLANK_CH(*cur))
7116 cur++;
7117 end = cur;
7118 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7119 end++;
7120 if (end == cur)
7121 break;
7122 tmp = xmlStrndup(cur, end - cur);
7123 ncName = xmlSplitQName3(tmp, &len);
7124 if (ncName != NULL) {
7125 prefix = xmlStrndup(tmp, len);
7126 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
7127 } else {
7128 prefix = NULL;
7129 ncName = tmp;
7130 }
William M. Bracke7091952004-05-11 15:09:58 +00007131 /* We won't do additional checks here,
7132 * since they have been performed during parsing. */
Daniel Veillard377e1a92004-04-16 16:30:05 +00007133 ns = xmlSearchNs(type->node->doc, type->node, prefix);
7134 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
7135 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
7136 if (tmp != NULL)
7137 xmlFree(tmp);
7138 if (prefix != NULL)
William M. Brack87640d52004-04-17 14:58:15 +00007139 xmlFree((void *)prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007140 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
7141 if ((ret == 0) || (ret == -1)) {
7142 return (ret);
7143 }
7144 cur = end;
7145 } while (*cur != 0);
7146
7147 if (type->subtypes != NULL) {
7148 subtype = type->subtypes;
7149 do {
7150 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
7151 if ((ret == 0) || (ret == -1)) {
7152 return (ret);
7153 }
7154 subtype = subtype->next;
7155 } while (subtype != NULL);
7156 }
7157 return (ret);
7158}
7159
7160/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007161 * xmlSchemaValidateSimpleValue:
7162 * @ctxt: a schema validation context
7163 * @type: the type declaration
7164 * @value: the value to validate
7165 *
7166 * Validate a value against a simple type
7167 *
7168 * Returns 0 if the value is valid, a positive error code
7169 * number otherwise and -1 in case of internal or API error.
7170 */
7171static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007172xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007173 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007174{
Daniel Veillard377e1a92004-04-16 16:30:05 +00007175 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
7176}
7177
7178/**
7179 * xmlSchemaValidateSimpleValue:
7180 * @ctxt: a schema validation context
7181 * @type: the type declaration
7182 * @value: the value to validate
William M. Bracke7091952004-05-11 15:09:58 +00007183 * @fireErrors: if 0, only internal errors will be fired;
7184 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00007185 *
7186 * Validate a value against a simple type
7187 *
7188 * Returns 0 if the value is valid, a positive error code
7189 * number otherwise and -1 in case of internal or API error.
7190 */
7191static int
7192xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
William M. Bracke7091952004-05-11 15:09:58 +00007193 xmlSchemaTypePtr type,
7194 const xmlChar * value,
7195 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00007196{
Daniel Veillard4255d502002-04-16 15:50:10 +00007197 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007198
Daniel Veillard4255d502002-04-16 15:50:10 +00007199 /*
7200 * First normalize the value accordingly to Schema Datatype
7201 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
William M. Bracke7091952004-05-11 15:09:58 +00007202 *
Daniel Veillard4255d502002-04-16 15:50:10 +00007203 * Then check the normalized value against the lexical space of the
7204 * type.
7205 */
7206 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007207 if (ctxt->value != NULL) {
7208 xmlSchemaFreeValue(ctxt->value);
7209 ctxt->value = NULL;
7210 }
7211 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
7212 ctxt->cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007213 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00007214 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
7215 "Failed to validate basic type %s\n",
7216 type->name, NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007217 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007218 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007219 xmlSchemaTypePtr base;
7220 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00007221
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007222 base = type->baseType;
7223 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00007224 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
7225 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007226 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007227 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007228 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007229
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007230 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00007231 * Do not validate facets or attributes when working on
7232 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007233 */
7234 if (ctxt->schema != NULL) {
7235 if (ret == 0) {
7236 facet = type->facets;
William M. Bracke7091952004-05-11 15:09:58 +00007237 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet,
7238 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007239 }
7240 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007241 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007242 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00007243
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007244 base = type->subtypes;
7245 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00007246 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
7247 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007248 } else {
7249 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00007250 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007251 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007252 const xmlChar *cur, *end;
7253 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007254 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00007255
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007256 base = type->subtypes;
7257 if (base == NULL) {
7258 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
7259 "Internal: List type %s has no base type\n",
7260 type->name, NULL);
7261 return (-1);
7262 }
7263 cur = value;
7264 do {
William M. Brack76e95df2003-10-18 16:20:14 +00007265 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007266 cur++;
7267 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00007268 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007269 end++;
7270 if (end == cur)
7271 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007272 tmp = xmlStrndup(cur, end - cur);
William M. Bracke7091952004-05-11 15:09:58 +00007273 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base,
7274 tmp, fireErrors);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007275 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007276 if (ret2 != 0)
7277 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007278 cur = end;
7279 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007280 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
7281 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
7282 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00007283 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
7284 "Failed to validate type %s\n", type->name, NULL);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007285 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007286 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007287 TODO
7288 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007289 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007290}
7291
7292/************************************************************************
7293 * *
7294 * DOM Validation code *
7295 * *
7296 ************************************************************************/
7297
7298static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007299 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007300static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007301 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +00007302 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007303static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007304 xmlNodePtr elem,
7305 xmlSchemaElementPtr elemDecl,
7306 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007307
Daniel Veillard3646d642004-06-02 19:19:14 +00007308
7309/**
7310 * xmlSchemaFreeAttrStates:
7311 * @state: a list of attribute states
7312 *
7313 * Free the given list of attribute states
7314 *
7315 */
7316static void
7317xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
7318{
7319 xmlSchemaAttrStatePtr tmp;
7320 while (state != NULL) {
7321 tmp = state;
7322 state = state->next;
7323 xmlFree(tmp);
7324 }
7325}
7326
Daniel Veillard4255d502002-04-16 15:50:10 +00007327/**
7328 * xmlSchemaRegisterAttributes:
7329 * @ctxt: a schema validation context
7330 * @attrs: a list of attributes
7331 *
7332 * Register the list of attributes as the set to be validated on that element
7333 *
7334 * Returns -1 in case of error, 0 otherwise
7335 */
7336static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007337xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
7338{
Daniel Veillard3646d642004-06-02 19:19:14 +00007339 xmlSchemaAttrStatePtr tmp;
7340
7341 ctxt->attr = NULL;
7342 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007343 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007344 if ((attrs->ns != NULL) &&
7345 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
7346 attrs = attrs->next;
7347 continue;
7348 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007349 tmp = (xmlSchemaAttrStatePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00007350 xmlMalloc(sizeof(xmlSchemaAttrState));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007351 if (tmp == NULL) {
7352 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007353 return (-1);
7354 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007355 tmp->attr = attrs;
7356 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
7357 tmp->next = NULL;
7358 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007359 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00007360 else
7361 ctxt->attrTop->next = tmp;
7362 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007363 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007364 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007365 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007366}
7367
7368/**
7369 * xmlSchemaCheckAttributes:
7370 * @ctxt: a schema validation context
7371 * @node: the node carrying it.
7372 *
7373 * Check that the registered set of attributes on the current node
7374 * has been properly validated.
7375 *
7376 * Returns 0 if validity constraints are met, 1 otherwise.
7377 */
7378static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007379xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7380{
Daniel Veillard4255d502002-04-16 15:50:10 +00007381 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00007382 xmlSchemaAttrStatePtr cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00007383
Daniel Veillard3646d642004-06-02 19:19:14 +00007384 cur = ctxt->attr;
7385 while ((cur != NULL) && (cur != ctxt->attrTop->next)) {
7386 if (cur->state != XML_SCHEMAS_ATTR_CHECKED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007387 ret = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00007388 if (cur->state == XML_SCHEMAS_ATTR_UNKNOWN)
William M. Bracke7091952004-05-11 15:09:58 +00007389 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
7390 "Attribute %s on %s is unknown\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00007391 cur->attr->name, node->name);
7392 else if (cur->state == XML_SCHEMAS_ATTR_PROHIBITED)
7393 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
7394 "Attribute %s on %s is prohibited\n",
7395 cur->attr->name, node->name);
7396 else if (cur->state == XML_SCHEMAS_ATTR_INVALID_VALUE)
7397 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRINVALID,
7398 "Attribute %s on %s does not match type\n",
7399 cur->attr->name, node->name);
7400 else if (cur->state == XML_SCHEMAS_ATTR_MISSING) {
7401 if (cur->decl->ref != NULL)
7402 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
7403 "Attribute %s on %s is required but missing\n",
7404 cur->decl->ref, node->name);
7405 else
7406 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
7407 "Attribute %s on %s is required but missing\n",
7408 cur->decl->name, node->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007409 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007410 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007411 cur = cur->next;
7412 }
7413
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007414 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007415}
7416
William M. Brack29aa7722004-05-12 00:27:56 +00007417#if 0 /* Not currently used - remove if ever needed */
Daniel Veillard4255d502002-04-16 15:50:10 +00007418/**
7419 * xmlSchemaValidateSimpleContent:
7420 * @ctxt: a schema validation context
7421 * @elem: an element
7422 * @type: the type declaration
7423 *
7424 * Validate the content of an element expected to be a simple type
7425 *
7426 * Returns 0 if the element is schemas valid, a positive error code
7427 * number otherwise and -1 in case of internal or API error.
7428 */
7429static int
7430xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007431 xmlNodePtr node ATTRIBUTE_UNUSED)
7432{
Daniel Veillard4255d502002-04-16 15:50:10 +00007433 xmlNodePtr child;
7434 xmlSchemaTypePtr type, base;
7435 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007436 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007437
7438 child = ctxt->node;
7439 type = ctxt->type;
7440
7441 /*
7442 * Validation Rule: Element Locally Valid (Type): 3.1.3
7443 */
7444 value = xmlNodeGetContent(child);
7445 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
7446 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007447 case XML_SCHEMA_TYPE_RESTRICTION:{
7448 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00007449
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007450 base = type->baseType;
7451 if (base != NULL) {
7452 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
7453 } else {
7454 TODO}
7455 if (ret == 0) {
7456 facet = type->facets;
7457 ret =
7458 xmlSchemaValidateFacets(ctxt, base, facet, value);
7459 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007460 /*
7461 * This should attempt to validate the attributes even
7462 * when validation of the value failed.
7463 */
7464 /*
7465 if (type->attributes != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00007466 ret = xmlSchemaValidateAttributes(ctxt, node,
7467 type->attributes);
7468 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007469 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007470 break;
7471 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007472 case XML_SCHEMA_TYPE_EXTENSION:{
7473 TODO
7474 break;
7475 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007476 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007477 TODO
7478 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007479 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007480 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00007481
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007482 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007483}
William M. Brack29aa7722004-05-12 00:27:56 +00007484#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00007485
7486/**
7487 * xmlSchemaValidateCheckNodeList
7488 * @nodelist: the list of nodes
7489 *
7490 * Check the node list is only made of text nodes and entities pointing
7491 * to text nodes
7492 *
7493 * Returns 1 if true, 0 if false and -1 in case of error
7494 */
7495static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007496xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
7497{
Daniel Veillard4255d502002-04-16 15:50:10 +00007498 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007499 if (nodelist->type == XML_ENTITY_REF_NODE) {
7500 TODO /* implement recursion in the entity content */
7501 }
7502 if ((nodelist->type != XML_TEXT_NODE) &&
7503 (nodelist->type != XML_COMMENT_NODE) &&
7504 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +00007505 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007506 return (0);
7507 }
7508 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007509 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007510 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007511}
7512
7513/**
7514 * xmlSchemaSkipIgnored:
7515 * @ctxt: a schema validation context
7516 * @type: the current type context
7517 * @node: the top node.
7518 *
7519 * Skip ignorable nodes in that context
7520 *
7521 * Returns the new sibling
7522 * number otherwise and -1 in case of internal or API error.
7523 */
7524static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00007525xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007526 xmlSchemaTypePtr type, xmlNodePtr node)
7527{
Daniel Veillard4255d502002-04-16 15:50:10 +00007528 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007529
Daniel Veillard4255d502002-04-16 15:50:10 +00007530 /*
7531 * TODO complete and handle entities
7532 */
7533 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007534 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00007535 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007536 ((node->type == XML_COMMENT_NODE) ||
7537 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
7538 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
7539 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
7540 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007541 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007542 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007543}
7544
7545/**
7546 * xmlSchemaValidateCallback:
7547 * @ctxt: a schema validation context
7548 * @name: the name of the element detected (might be NULL)
7549 * @type: the type
7550 *
7551 * A transition has been made in the automata associated to an element
7552 * content model
7553 */
7554static void
7555xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007556 const xmlChar * name ATTRIBUTE_UNUSED,
7557 xmlSchemaTypePtr type, xmlNodePtr node)
7558{
Daniel Veillard4255d502002-04-16 15:50:10 +00007559 xmlSchemaTypePtr oldtype = ctxt->type;
7560 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007561
Daniel Veillard4255d502002-04-16 15:50:10 +00007562#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00007563 xmlGenericError(xmlGenericErrorContext,
7564 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007565 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00007566#endif
7567 ctxt->type = type;
7568 ctxt->node = node;
7569 xmlSchemaValidateContent(ctxt, node);
7570 ctxt->type = oldtype;
7571 ctxt->node = oldnode;
7572}
7573
7574
7575#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007576
Daniel Veillard4255d502002-04-16 15:50:10 +00007577/**
7578 * xmlSchemaValidateSimpleRestrictionType:
7579 * @ctxt: a schema validation context
7580 * @node: the top node.
7581 *
7582 * Validate the content of a restriction type.
7583 *
7584 * Returns 0 if the element is schemas valid, a positive error code
7585 * number otherwise and -1 in case of internal or API error.
7586 */
7587static int
7588xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
7589 xmlNodePtr node)
7590{
7591 xmlNodePtr child;
7592 xmlSchemaTypePtr type;
7593 int ret;
7594
7595 child = ctxt->node;
7596 type = ctxt->type;
7597
7598 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00007599 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7600 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
7601 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007602 return (-1);
7603 }
7604 /*
7605 * Only text and text based entities references shall be found there
7606 */
7607 ret = xmlSchemaValidateCheckNodeList(child);
7608 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007609 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7610 "Internal error: xmlSchemaValidateSimpleType %s content\n",
7611 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007612 return (-1);
7613 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007614 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
7615 "Element %s content is not a simple type\n",
7616 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007617 return (-1);
7618 }
7619 ctxt->type = type->subtypes;
7620 xmlSchemaValidateContent(ctxt, node);
7621 ctxt->type = type;
7622 return (ret);
7623}
7624#endif
7625
7626/**
7627 * xmlSchemaValidateSimpleType:
7628 * @ctxt: a schema validation context
7629 * @node: the top node.
7630 *
7631 * Validate the content of an simple type.
7632 *
7633 * Returns 0 if the element is schemas valid, a positive error code
7634 * number otherwise and -1 in case of internal or API error.
7635 */
7636static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007637xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7638{
Daniel Veillard4255d502002-04-16 15:50:10 +00007639 xmlNodePtr child;
William M. Bracke7091952004-05-11 15:09:58 +00007640 xmlSchemaTypePtr type, base, variety;
Daniel Veillard4255d502002-04-16 15:50:10 +00007641 xmlAttrPtr attr;
7642 int ret;
William M. Bracke7091952004-05-11 15:09:58 +00007643 xmlChar *value;
7644
Daniel Veillard4255d502002-04-16 15:50:10 +00007645
7646 child = ctxt->node;
7647 type = ctxt->type;
7648
7649 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00007650 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7651 "Internal error: xmlSchemaValidateSimpleType %s\n",
7652 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007653 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007654 }
7655 /*
7656 * Only text and text based entities references shall be found there
7657 */
7658 ret = xmlSchemaValidateCheckNodeList(child);
7659 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007660 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7661 "Internal error: xmlSchemaValidateSimpleType %s content\n",
7662 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007663 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007664 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007665 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
7666 "Element %s content is not a simple type\n",
7667 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007668 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007669 }
7670 /*
7671 * Validation Rule: Element Locally Valid (Type): 3.1.1
William M. Bracke7091952004-05-11 15:09:58 +00007672 */
7673
Daniel Veillard4255d502002-04-16 15:50:10 +00007674 attr = node->properties;
7675 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007676 if ((attr->ns == NULL) ||
7677 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
7678 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
7679 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
7680 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
7681 (!xmlStrEqual
7682 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
William M. Bracke7091952004-05-11 15:09:58 +00007683 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
7684 "Element %s: attribute %s should not be present\n",
7685 node->name, attr->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007686 return (ctxt->err);
7687 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007688 }
William M. Bracke7091952004-05-11 15:09:58 +00007689 /* TODO:
7690 * If {variety} is ·atomic· then the {variety} of {base type definition}
7691 * must be ·atomic·.
7692 * If {variety} is ·list· then the {variety} of {item type definition}
7693 * must be either ·atomic· or ·union·.
7694 * If {variety} is ·union· then {member type definitions} must be a list
7695 * of datatype definitions.
7696 */
7697 if (type->subtypes == NULL) {
7698 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7699 "Internal error: xmlSchemaValidateSimpleType; "
7700 "simple type %s does not define a variety\n",
7701 node->name, NULL);
7702 return (ctxt->err);
7703 }
7704 /* Varieties: Restriction or List or Union. */
7705 variety = type->subtypes;
7706 ctxt->type = variety;
7707 value = xmlNodeGetContent(child);
7708 switch (variety->type) {
7709 case XML_SCHEMA_TYPE_RESTRICTION:{
7710 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00007711
William M. Bracke7091952004-05-11 15:09:58 +00007712 base = variety->baseType;
7713 if (base != NULL) {
7714 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
7715 } else {
7716 TODO}
7717 if (ret == 0) {
7718 facet = variety->facets;
7719 ret =
7720 xmlSchemaValidateFacets(ctxt, base, facet, value);
7721 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007722 /* Removed due to changes of attribute validation:
William M. Bracke7091952004-05-11 15:09:58 +00007723 if ((ret == 0) && (variety->attributes != NULL)) {
7724 ret = xmlSchemaValidateAttributes(ctxt, node,
7725 variety->attributes);
7726 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007727 */
William M. Bracke7091952004-05-11 15:09:58 +00007728 break;
7729 }
7730 case XML_SCHEMA_TYPE_LIST:
7731 case XML_SCHEMA_TYPE_UNION: {
7732 ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
7733 break;
7734 }
7735 default:{
7736 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7737 "Internal error: xmlSchemaValidateSimpleType; "
7738 "simple type %s defines unknown content: %s\n",
7739 variety->name, NULL);
7740 ret = ctxt->err;
7741 }
7742 }
7743 if (value != NULL)
7744 xmlFree(value);
7745
7746 /* This was removed, since a simple content is not a content of a
7747 * simple type, but of a complex type.
7748 * ret = xmlSchemaValidateSimpleContent(ctxt, node);
7749 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007750 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007751 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007752}
7753
7754/**
7755 * xmlSchemaValidateElementType:
7756 * @ctxt: a schema validation context
7757 * @node: the top node.
7758 *
7759 * Validate the content of an element type.
7760 * Validation Rule: Element Locally Valid (Complex Type)
7761 *
7762 * Returns 0 if the element is schemas valid, a positive error code
7763 * number otherwise and -1 in case of internal or API error.
7764 */
7765static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007766xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7767{
Daniel Veillard4255d502002-04-16 15:50:10 +00007768 xmlNodePtr child;
7769 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007770 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00007771 xmlSchemaElementPtr decl;
Daniel Veillard3646d642004-06-02 19:19:14 +00007772 int ret;
7773 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
7774
7775 /*
7776 * TODO: Look into "xmlSchemaValidateElement" for missing parts, which should
7777 * go in here as well.
7778 */
7779
7780 /* TODO: Is this one called always with an element declaration as the
7781 * context's type?
7782 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007783
7784 oldregexp = ctxt->regexp;
7785
7786 child = ctxt->node;
7787 type = ctxt->type;
7788
7789 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00007790 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7791 "Internal error: xmlSchemaValidateElementType\n",
7792 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007793 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007794 }
7795 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007796 if (type->minOccurs > 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007797 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
7798 "Element %s: missing child %s\n",
7799 node->name, type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007800 }
7801 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00007802 }
7803
7804 /*
7805 * Verify the element matches
7806 */
7807 if (!xmlStrEqual(child->name, type->name)) {
William M. Bracke7091952004-05-11 15:09:58 +00007808 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
7809 "Element %s: missing child %s found %s\n",
7810 node->name, type->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007811 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00007812 }
7813 /*
7814 * Verify the attributes
7815 */
Daniel Veillard3646d642004-06-02 19:19:14 +00007816
7817 attrs = ctxt->attr;
7818 attrTop = ctxt->attrTop;
7819
Daniel Veillard4255d502002-04-16 15:50:10 +00007820 xmlSchemaRegisterAttributes(ctxt, child->properties);
Daniel Veillard3646d642004-06-02 19:19:14 +00007821
7822 /*
7823 * An element declaration does not hold any information about
7824 * attributes; thus, the following was removed.
7825 */
7826 /* xmlSchemaValidateAttributes(ctxt, child, type->attributes); */
7827
Daniel Veillard4255d502002-04-16 15:50:10 +00007828 /*
7829 * Verify the element content recursively
7830 */
7831 decl = (xmlSchemaElementPtr) type;
7832 oldregexp = ctxt->regexp;
7833 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007834 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
7835 (xmlRegExecCallbacks)
7836 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00007837#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007838 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00007839#endif
7840 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007841 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
7842 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00007843
7844 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007845 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007846#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007847 xmlGenericError(xmlGenericErrorContext,
7848 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007849#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007850 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007851 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
7852 "Element %s content check failed\n",
7853 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007854 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007855 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
7856 "Element %s content check failure\n",
7857 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007858#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007859 } else {
7860 xmlGenericError(xmlGenericErrorContext,
7861 "Element %s content check succeeded\n",
7862 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00007863
7864#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007865 }
7866 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00007867 }
7868 /*
7869 * Verify that all attributes were Schemas-validated
7870 */
7871 xmlSchemaCheckAttributes(ctxt, node);
Daniel Veillard3646d642004-06-02 19:19:14 +00007872 if (ctxt->attr != NULL)
7873 xmlSchemaFreeAttributeStates(ctxt->attr);
7874 ctxt->attr = attrs;
7875 ctxt->attrTop = attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +00007876 ctxt->regexp = oldregexp;
Daniel Veillard4255d502002-04-16 15:50:10 +00007877 ctxt->node = child;
7878 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007879 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00007880}
7881
7882/**
7883 * xmlSchemaValidateBasicType:
7884 * @ctxt: a schema validation context
7885 * @node: the top node.
7886 *
7887 * Validate the content of an element expected to be a basic type type
7888 *
7889 * Returns 0 if the element is schemas valid, a positive error code
7890 * number otherwise and -1 in case of internal or API error.
7891 */
7892static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007893xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7894{
Daniel Veillard4255d502002-04-16 15:50:10 +00007895 int ret;
7896 xmlNodePtr child, cur;
7897 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007898 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00007899
7900 child = ctxt->node;
7901 type = ctxt->type;
7902
7903 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00007904 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7905 "Internal error: xmlSchemaValidateBasicType\n",
7906 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007907 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007908 }
7909 /*
7910 * First check the content model of the node.
7911 */
7912 cur = child;
7913 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007914 switch (cur->type) {
7915 case XML_TEXT_NODE:
7916 case XML_CDATA_SECTION_NODE:
7917 case XML_PI_NODE:
7918 case XML_COMMENT_NODE:
7919 case XML_XINCLUDE_START:
7920 case XML_XINCLUDE_END:
7921 break;
7922 case XML_ENTITY_REF_NODE:
7923 case XML_ENTITY_NODE:
7924 TODO break;
7925 case XML_ELEMENT_NODE:
William M. Bracke7091952004-05-11 15:09:58 +00007926 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
7927 "Element %s: child %s should not be present\n",
7928 node->name, cur->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007929 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00007930 case XML_ATTRIBUTE_NODE:
7931 case XML_DOCUMENT_NODE:
7932 case XML_DOCUMENT_TYPE_NODE:
7933 case XML_DOCUMENT_FRAG_NODE:
7934 case XML_NOTATION_NODE:
7935 case XML_HTML_DOCUMENT_NODE:
7936 case XML_DTD_NODE:
7937 case XML_ELEMENT_DECL:
7938 case XML_ATTRIBUTE_DECL:
7939 case XML_ENTITY_DECL:
7940 case XML_NAMESPACE_DECL:
7941#ifdef LIBXML_DOCB_ENABLED
7942 case XML_DOCB_DOCUMENT_NODE:
7943#endif
William M. Bracke7091952004-05-11 15:09:58 +00007944 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
7945 "Element %s: node type of node unexpected here\n",
7946 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007947 return (ctxt->err);
7948 }
7949 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007950 }
7951 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007952 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007953 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007954 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00007955
7956 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007957 xmlSchemaFreeValue(ctxt->value);
7958 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007959 }
7960 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
7961 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007962 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00007963 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007964 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
7965 "Element %s: failed to validate basic type %s\n",
7966 node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00007967 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007968 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007969}
7970
7971/**
7972 * xmlSchemaValidateComplexType:
7973 * @ctxt: a schema validation context
7974 * @node: the top node.
7975 *
7976 * Validate the content of an element expected to be a complex type type
7977 * xmlschema-1.html#cvc-complex-type
7978 * Validation Rule: Element Locally Valid (Complex Type)
7979 *
7980 * Returns 0 if the element is schemas valid, a positive error code
7981 * number otherwise and -1 in case of internal or API error.
7982 */
7983static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007984xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7985{
Daniel Veillard4255d502002-04-16 15:50:10 +00007986 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00007987 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007988 int ret;
7989
Daniel Veillard3646d642004-06-02 19:19:14 +00007990 /* TODO: Handle xsd:restriction & xsd:extension */
7991
Daniel Veillard4255d502002-04-16 15:50:10 +00007992 child = ctxt->node;
7993 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00007994 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00007995
Daniel Veillard4255d502002-04-16 15:50:10 +00007996 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007997 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007998 if (type->baseType != NULL) {
7999 } else if (child != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008000 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY,
8001 "Element %s is supposed to be empty\n",
8002 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008003 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008004 /* Removed due to changes of attribute validation:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008005 if (type->attributes != NULL) {
8006 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
8007 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008008 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008009 subtype = type->subtypes;
8010 while (subtype != NULL) {
8011 ctxt->type = subtype;
8012 xmlSchemaValidateComplexType(ctxt, node);
8013 subtype = subtype->next;
8014 }
8015 break;
8016 case XML_SCHEMA_CONTENT_ELEMENTS:
8017 case XML_SCHEMA_CONTENT_MIXED:
8018 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
8019 /*
8020 * Skip ignorable nodes in that context
8021 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008022 /* ComplexType, ComplexContent */
8023 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008024 child = xmlSchemaSkipIgnored(ctxt, type, child);
8025 while (child != NULL) {
8026 if (child->type == XML_ELEMENT_NODE) {
8027 ret = xmlRegExecPushString(ctxt->regexp,
8028 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00008029#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008030 if (ret < 0)
8031 xmlGenericError(xmlGenericErrorContext,
8032 " --> %s Error\n", child->name);
8033 else
8034 xmlGenericError(xmlGenericErrorContext,
8035 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008036#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008037 }
8038 child = child->next;
8039 /*
8040 * Skip ignorable nodes in that context
8041 */
8042 child = xmlSchemaSkipIgnored(ctxt, type, child);
8043 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008044 }
8045
William M. Bracke7091952004-05-11 15:09:58 +00008046 if (((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
8047 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS)) &&
8048 (type->subtypes != NULL)) {
8049 TODO
8050 }
8051
Daniel Veillard3646d642004-06-02 19:19:14 +00008052 /* Removed due to changes of attribute validation:
Daniel Veillardf2a12832003-11-24 13:04:35 +00008053 if (type->attributes != NULL) {
8054 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
8055 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008056 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008057 break;
8058 case XML_SCHEMA_CONTENT_BASIC:{
8059 if (type->subtypes != NULL) {
8060 ctxt->type = type->subtypes;
8061 xmlSchemaValidateComplexType(ctxt, node);
8062 }
8063 if (type->baseType != NULL) {
8064 ctxt->type = type->baseType;
William M. Bracke7091952004-05-11 15:09:58 +00008065 if (type->baseType->type == XML_SCHEMA_TYPE_BASIC)
8066 xmlSchemaValidateBasicType(ctxt, node);
8067 else if (type->baseType->type == XML_SCHEMA_TYPE_COMPLEX)
8068 xmlSchemaValidateComplexType(ctxt, node);
Daniel Veillard3646d642004-06-02 19:19:14 +00008069 /* TODO: This might be incorrect. */
William M. Bracke7091952004-05-11 15:09:58 +00008070 else if (type->baseType->type == XML_SCHEMA_TYPE_SIMPLE)
8071 xmlSchemaValidateSimpleType(ctxt, node);
8072 else
8073 xmlGenericError(xmlGenericErrorContext,
8074 "unexpected content type of base: %d\n",
8075 type->contentType);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008076 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008077 /* Removed due to changes of attribute validation:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008078 if (type->attributes != NULL) {
8079 xmlSchemaValidateAttributes(ctxt, node,
8080 type->attributes);
8081 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008082 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008083 ctxt->type = type;
8084 break;
8085 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008086 case XML_SCHEMA_CONTENT_SIMPLE:{
8087 if (type->subtypes != NULL) {
8088 ctxt->type = type->subtypes;
8089 xmlSchemaValidateComplexType(ctxt, node);
8090 }
8091 if (type->baseType != NULL) {
8092 ctxt->type = type->baseType;
8093 xmlSchemaValidateComplexType(ctxt, node);
8094 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008095 /* Removed due to changes of attribute validation:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008096 if (type->attributes != NULL) {
8097 xmlSchemaValidateAttributes(ctxt, node,
8098 type->attributes);
8099 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008100 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008101 ctxt->type = type;
8102 break;
8103 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008104 default:
8105 TODO xmlGenericError(xmlGenericErrorContext,
8106 "unimplemented content type %d\n",
8107 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00008108 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008109 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
8110 xmlSchemaValidateAttributes(ctxt, node, type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008111 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008112}
8113
8114/**
8115 * xmlSchemaValidateContent:
8116 * @ctxt: a schema validation context
8117 * @elem: an element
8118 * @type: the type declaration
8119 *
8120 * Validate the content of an element against the type.
8121 *
8122 * Returns 0 if the element is schemas valid, a positive error code
8123 * number otherwise and -1 in case of internal or API error.
8124 */
8125static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008126xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
8127{
Daniel Veillard4255d502002-04-16 15:50:10 +00008128 xmlNodePtr child;
8129 xmlSchemaTypePtr type;
8130
8131 child = ctxt->node;
8132 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00008133 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00008134
Daniel Veillard3646d642004-06-02 19:19:14 +00008135 /*
8136 * Removed, since redundant.
8137 */
8138 /* xmlSchemaValidateAttributes(ctxt, node, type->attributes); */
Daniel Veillard82bbbd42003-05-11 20:16:09 +00008139 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00008140
Daniel Veillard4255d502002-04-16 15:50:10 +00008141 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008142 case XML_SCHEMA_TYPE_ANY:
8143 /* Any type will do it, fine */
8144 TODO /* handle recursivity */
8145 break;
8146 case XML_SCHEMA_TYPE_COMPLEX:
8147 xmlSchemaValidateComplexType(ctxt, node);
8148 break;
8149 case XML_SCHEMA_TYPE_ELEMENT:{
8150 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
8151
8152 /*
8153 * Handle element reference here
8154 */
8155 if (decl->ref != NULL) {
8156 if (decl->refDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008157 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
8158 "Internal error: element reference %s "
8159 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008160 return (-1);
8161 }
8162 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
8163 decl = decl->refDecl;
8164 }
William M. Bracke7091952004-05-11 15:09:58 +00008165 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008166 xmlSchemaValidateElementType(ctxt, node);
8167 ctxt->type = type;
8168 break;
8169 }
8170 case XML_SCHEMA_TYPE_BASIC:
8171 xmlSchemaValidateBasicType(ctxt, node);
8172 break;
8173 case XML_SCHEMA_TYPE_FACET:
8174 TODO break;
8175 case XML_SCHEMA_TYPE_SIMPLE:
8176 xmlSchemaValidateSimpleType(ctxt, node);
8177 break;
8178 case XML_SCHEMA_TYPE_SEQUENCE:
8179 TODO break;
8180 case XML_SCHEMA_TYPE_CHOICE:
8181 TODO break;
8182 case XML_SCHEMA_TYPE_ALL:
8183 TODO break;
8184 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8185 TODO break;
8186 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8187 TODO break;
8188 case XML_SCHEMA_TYPE_UR:
8189 TODO break;
8190 case XML_SCHEMA_TYPE_RESTRICTION:
8191 /*xmlSchemaValidateRestrictionType(ctxt, node); */
8192 TODO break;
8193 case XML_SCHEMA_TYPE_EXTENSION:
8194 TODO break;
8195 case XML_SCHEMA_TYPE_ATTRIBUTE:
8196 TODO break;
8197 case XML_SCHEMA_TYPE_GROUP:
8198 TODO break;
8199 case XML_SCHEMA_TYPE_NOTATION:
8200 TODO break;
8201 case XML_SCHEMA_TYPE_LIST:
8202 TODO break;
8203 case XML_SCHEMA_TYPE_UNION:
8204 TODO break;
8205 case XML_SCHEMA_FACET_MININCLUSIVE:
8206 TODO break;
8207 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8208 TODO break;
8209 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8210 TODO break;
8211 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8212 TODO break;
8213 case XML_SCHEMA_FACET_TOTALDIGITS:
8214 TODO break;
8215 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8216 TODO break;
8217 case XML_SCHEMA_FACET_PATTERN:
8218 TODO break;
8219 case XML_SCHEMA_FACET_ENUMERATION:
8220 TODO break;
8221 case XML_SCHEMA_FACET_WHITESPACE:
8222 TODO break;
8223 case XML_SCHEMA_FACET_LENGTH:
8224 TODO break;
8225 case XML_SCHEMA_FACET_MAXLENGTH:
8226 TODO break;
8227 case XML_SCHEMA_FACET_MINLENGTH:
8228 TODO break;
8229 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
8230 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +00008231 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8232 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00008233 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008234 /*
8235 * Removed, since redundant.
8236 */
8237 /* xmlSchemaValidateAttributes(ctxt, node, type->attributes); */
Daniel Veillard4255d502002-04-16 15:50:10 +00008238
8239 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008240 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008241 ctxt->node = ctxt->node->next;
8242 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008243 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008244}
8245
8246/**
8247 * xmlSchemaValidateType:
8248 * @ctxt: a schema validation context
8249 * @elem: an element
8250 * @type: the list of type declarations
8251 *
8252 * Validate the content of an element against the types.
8253 *
8254 * Returns 0 if the element is schemas valid, a positive error code
8255 * number otherwise and -1 in case of internal or API error.
8256 */
8257static int
8258xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008259 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
8260{
Daniel Veillard4255d502002-04-16 15:50:10 +00008261 xmlChar *nil;
8262
Daniel Veillard2db8c122003-07-08 12:16:59 +00008263 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008264 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00008265
Daniel Veillard3646d642004-06-02 19:19:14 +00008266 /* This one is called by "xmlSchemaValidateElementType" and
8267 * "xmlSchemaValidateElement".
8268 */
8269
Daniel Veillard4255d502002-04-16 15:50:10 +00008270 /*
8271 * 3.3.4 : 2
8272 */
8273 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
William M. Bracke7091952004-05-11 15:09:58 +00008274 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
8275 "Element declaration %s is abstract\n",
8276 elemDecl->name, NULL);
8277 /* Changed, since the element declaration is abstract and not
8278 * the element itself. */
8279 /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
8280 "Element %s is abstract\n", elem->name, NULL); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008281 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008282 }
8283 /*
8284 * 3.3.4: 3
8285 */
8286 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
8287 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008288 /* 3.3.4: 3.2 */
8289 if (xmlStrEqual(nil, BAD_CAST "true")) {
8290 if (elem->children != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008291 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
8292 "Element %s is not empty\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008293 return (ctxt->err);
8294 }
8295 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
8296 (elemDecl->value != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00008297 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
8298 "Empty element %s cannot get a fixed value\n",
8299 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008300 return (ctxt->err);
8301 }
8302 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008303 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008304 /* 3.3.4: 3.1 */
8305 if (nil != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008306 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
8307 "Element %s with xs:nil but not nillable\n",
8308 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008309 xmlFree(nil);
8310 return (ctxt->err);
8311 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008312 }
8313
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008314 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00008315
8316 ctxt->type = elemDecl->subtypes;
8317 ctxt->node = elem->children;
8318 xmlSchemaValidateContent(ctxt, elem);
Daniel Veillard3646d642004-06-02 19:19:14 +00008319 /* Removed, since an element declaration does not hold any attribute
8320 * declarations */
8321 /* xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008322
8323 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008324}
8325
8326
8327/**
8328 * xmlSchemaValidateAttributes:
8329 * @ctxt: a schema validation context
8330 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +00008331 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +00008332 *
8333 * Validate the attributes of an element.
8334 *
8335 * Returns 0 if the element is schemas valid, a positive error code
8336 * number otherwise and -1 in case of internal or API error.
8337 */
8338static int
Daniel Veillard3646d642004-06-02 19:19:14 +00008339xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008340{
Daniel Veillard3646d642004-06-02 19:19:14 +00008341 int ret;
8342 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +00008343 xmlChar *value;
Daniel Veillard3646d642004-06-02 19:19:14 +00008344 xmlSchemaAttributeLinkPtr attrUse;
8345 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00008346 int found;
Daniel Veillard3646d642004-06-02 19:19:14 +00008347 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop;
8348#ifdef DEBUG_ATTR_VALIDATION
8349 int redundant = 0;
8350#endif
8351 if (type->type != XML_SCHEMA_TYPE_COMPLEX) {
8352 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INTERNAL,
8353 "Internal error: xmlSchemaValidateAttributes: "
8354 "given type \"%s\"is not a complexType\n",
8355 type->name, NULL);
8356 return(-1);
8357 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008358
Daniel Veillard3646d642004-06-02 19:19:14 +00008359 if ((type->attributeUses == NULL) && (type->attributeWildcard == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008360 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008361
8362 attrUse = type->attributeUses;
8363
8364 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00008365 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00008366 attrDecl = attrUse->attr;
8367#ifdef DEBUG_ATTR_VALIDATION
8368 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
8369 printf("attr use - use: %d\n", attrDecl->occurs);
8370#endif
8371 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
8372
8373 if (curState->decl == attrUse->attr) {
8374#ifdef DEBUG_ATTR_VALIDATION
8375 redundant = 1;
8376#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008377 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008378 attr = curState->attr;
8379#ifdef DEBUG_ATTR_VALIDATION
8380 printf("attr - name: %s\n", attr->name);
8381 if (attr->ns != NULL)
8382 printf("attr - ns: %s\n", attr->ns->href);
8383 else
8384 printf("attr - ns: none\n");
8385#endif
8386 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008387 if (attr == NULL)
8388 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +00008389 if (attrDecl->ref != NULL) {
8390 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008391 continue;
8392 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008393 if ((attrDecl->refNs == NULL) ||
8394 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008395 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +00008396 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008397 continue;
8398 }
8399 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00008400 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008401 continue;
8402 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008403 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008404 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008405 if (attr->ns == NULL) {
8406 /*
William M. Bracke7091952004-05-11 15:09:58 +00008407 * accept an unqualified attribute only if the target
8408 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008409 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008410 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +00008411 /*
8412 * This check was removed, since the target namespace
8413 * was evaluated during parsing and already took
8414 * "attributeFormDefault" into account.
8415 */
8416 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008417 continue;
8418 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00008419 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008420 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +00008421 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008422 attr->ns->href))
8423 continue;
8424 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008425 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008426#ifdef DEBUG_ATTR_VALIDATION
8427 printf("found\n");
8428#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00008429 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00008430 ctxt->cur = (xmlNodePtr) attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00008431
Daniel Veillard3646d642004-06-02 19:19:14 +00008432 if (attrDecl->subtypes == NULL) {
8433 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
8434 curState->decl = attrDecl;
8435 /*
8436 * This could be put into "xmlSchemaCheckAttributes" as well, but
8437 * since it reports an internal error, it better stays here to ease
8438 * debugging.
8439 */
William M. Bracke7091952004-05-11 15:09:58 +00008440 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
8441 "Internal error: attribute %s type not resolved\n",
8442 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008443 continue;
8444 }
8445 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00008446 ret = xmlSchemaValidateSimpleValue(ctxt, attrDecl->subtypes,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008447 value);
Daniel Veillard3646d642004-06-02 19:19:14 +00008448 if (ret != 0)
8449 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
8450 else
8451 curState->state = XML_SCHEMAS_ATTR_CHECKED;
8452 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008453 if (value != NULL) {
8454 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +00008455 }
8456 }
8457 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
8458 xmlSchemaAttrStatePtr tmp;
8459
8460#ifdef DEBUG_ATTR_VALIDATION
8461 printf("required attr not found\n");
8462#endif
8463 /*
8464 * Add a new dummy attribute state.
8465 */
8466 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
8467 if (tmp == NULL) {
8468 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
8469 return (-1);
8470 }
8471 tmp->attr = NULL;
8472 tmp->state = XML_SCHEMAS_ATTR_MISSING;
8473 tmp->decl = attrDecl;
8474 tmp->next = NULL;
8475
8476 if (reqAttrStates == NULL) {
8477 reqAttrStates = tmp;
8478 reqAttrStatesTop = tmp;
8479 } else {
8480 reqAttrStatesTop->next = tmp;
8481 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008482 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008483
8484 }
8485 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008486 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008487 /*
8488 * Add required attributes to the attribute states of the context.
8489 */
8490 if (reqAttrStates != NULL) {
8491 if (ctxt->attr == NULL) {
8492 ctxt->attr = reqAttrStates;
8493 } else {
8494 ctxt->attrTop->next = reqAttrStates;
8495 }
8496 ctxt->attrTop = reqAttrStatesTop;
8497 }
8498 /*
8499 * Process wildcards.
8500 */
8501 if (type->attributeWildcard != NULL) {
8502#ifdef DEBUG_ATTR_VALIDATION
8503 xmlSchemaWildcardNsPtr ns;
8504 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
8505 if (type->attributeWildcard->any)
8506 printf("type: any\n");
8507 else if (type->attributeWildcard->negNsSet != NULL) {
8508 printf("type: negated\n");
8509 if (type->attributeWildcard->negNsSet->value == NULL)
8510 printf("ns: (absent)\n");
8511 else
8512 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
8513 } else if (type->attributeWildcard->nsSet != NULL) {
8514 printf("type: set\n");
8515 ns = type->attributeWildcard->nsSet;
8516 while (ns != NULL) {
8517 if (ns->value == NULL)
8518 printf("ns: (absent)\n");
8519 else
8520 printf("ns: %s\n", ns->value);
8521 ns = ns->next;
8522 }
8523 } else
8524 printf("empty\n");
8525
8526#endif
8527 /*
8528 * TODO: Implement processContents.
8529 */
8530 curState = ctxt->attr;
8531 while (curState != NULL) {
8532 if ((curState->state == XML_SCHEMAS_ATTR_UNKNOWN) &&
8533 (curState->attr != NULL)) {
8534 if (curState->attr->ns != NULL) {
8535 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
8536 curState->attr->ns->href))
8537 curState->state = XML_SCHEMAS_ATTR_CHECKED;
8538 } else if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
8539 NULL))
8540 curState->state = XML_SCHEMAS_ATTR_CHECKED;
8541 }
8542 curState = curState->next;
8543 }
8544 }
8545
8546#ifdef DEBUG_ATTR_VALIDATION
8547 if (redundant)
8548 xmlGenericError(xmlGenericErrorContext,
8549 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
8550 type->name);
8551#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008552 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008553}
8554
8555/**
8556 * xmlSchemaValidateElement:
8557 * @ctxt: a schema validation context
8558 * @elem: an element
8559 *
8560 * Validate an element in a tree
8561 *
8562 * Returns 0 if the element is schemas valid, a positive error code
8563 * number otherwise and -1 in case of internal or API error.
8564 */
8565static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008566xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
8567{
Daniel Veillard4255d502002-04-16 15:50:10 +00008568 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +00008569 int ret;
8570 xmlSchemaAttrStatePtr attrs, attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +00008571
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008572 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008573 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8574 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008575 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008576 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8577 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008578 }
8579 /*
8580 * special case whe elementFormDefault is unqualified for top-level elem.
8581 */
William M. Bracke7091952004-05-11 15:09:58 +00008582 /*
8583 * This was removed, since elementFormDefault does not apply to top-level
8584 * element declarations.
8585 */
8586 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008587 if ((elemDecl == NULL) && (elem->ns != NULL) &&
8588 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
8589 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
8590 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
8591 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8592 elem->name, NULL, NULL);
8593 }
William M. Bracke7091952004-05-11 15:09:58 +00008594 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008595
Daniel Veillard4255d502002-04-16 15:50:10 +00008596 /*
8597 * 3.3.4 : 1
8598 */
8599 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008600 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
8601 "Element %s not declared\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008602 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008603 }
8604 if (elemDecl->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008605 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
8606 "Element %s has no type\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008607 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008608 }
8609 /*
8610 * Verify the attributes
8611 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008612 attrs = ctxt->attr;
8613 attrTop = ctxt->attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +00008614 xmlSchemaRegisterAttributes(ctxt, elem->properties);
Daniel Veillard4255d502002-04-16 15:50:10 +00008615 /*
8616 * Verify the element content recursively
8617 */
8618 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008619 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
8620 (xmlRegExecCallbacks)
8621 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008622#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008623 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008624#endif
8625 }
8626 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008627 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008628 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008629#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008630 xmlGenericError(xmlGenericErrorContext,
8631 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008632#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008633 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00008634 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
8635 "Element %s content check failed\n",
8636 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008637 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00008638 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
8639 "Element %s content check failed\n",
8640 elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008641#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008642 } else {
8643 xmlGenericError(xmlGenericErrorContext,
8644 "Element %s content check succeeded\n",
8645 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008646
8647#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008648 }
8649 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00008650 }
8651 /*
8652 * Verify that all attributes were Schemas-validated
8653 */
8654 xmlSchemaCheckAttributes(ctxt, elem);
Daniel Veillard3646d642004-06-02 19:19:14 +00008655 if (ctxt->attr != NULL)
8656 xmlSchemaFreeAttributeStates(ctxt->attr);
8657 ctxt->attr = attrs;
8658 ctxt->attrTop = attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008659
8660 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008661}
8662
8663/**
8664 * xmlSchemaValidateDocument:
8665 * @ctxt: a schema validation context
8666 * @doc: a parsed document tree
8667 *
8668 * Validate a document tree in memory.
8669 *
8670 * Returns 0 if the document is schemas valid, a positive error code
8671 * number otherwise and -1 in case of internal or API error.
8672 */
8673static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008674xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
8675{
Daniel Veillard4255d502002-04-16 15:50:10 +00008676 xmlNodePtr root;
8677 xmlSchemaElementPtr elemDecl;
8678
8679 root = xmlDocGetRootElement(doc);
8680 if (root == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008681 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
8682 "document has no root\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008683 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008684 }
William M. Bracke7091952004-05-11 15:09:58 +00008685
Daniel Veillard4255d502002-04-16 15:50:10 +00008686 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008687 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8688 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008689 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008690 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8691 root->name, NULL, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00008692
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008693 /*
8694 * special case whe elementFormDefault is unqualified for top-level elem.
8695 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008696 /* Removed, since elementFormDefault does not apply to top level
8697 * elements */
8698 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008699 if ((elemDecl == NULL) && (root->ns != NULL) &&
8700 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
8701 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
8702 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8703 root->name, NULL, NULL);
8704 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008705 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008706
Daniel Veillard4255d502002-04-16 15:50:10 +00008707 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008708 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
8709 "Element %s not declared\n", root->name, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00008710 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00008711 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
Daniel Veillard3646d642004-06-02 19:19:14 +00008712 "Root element %s not global\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008713 }
8714 /*
8715 * Okay, start the recursive validation
8716 */
8717 xmlSchemaValidateElement(ctxt, root);
8718
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008719 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008720}
8721
8722/************************************************************************
8723 * *
8724 * SAX Validation code *
8725 * *
8726 ************************************************************************/
8727
8728/************************************************************************
8729 * *
8730 * Validation interfaces *
8731 * *
8732 ************************************************************************/
8733
8734/**
8735 * xmlSchemaNewValidCtxt:
8736 * @schema: a precompiled XML Schemas
8737 *
8738 * Create an XML Schemas validation context based on the given schema
8739 *
8740 * Returns the validation context or NULL in case of error
8741 */
8742xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008743xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
8744{
Daniel Veillard4255d502002-04-16 15:50:10 +00008745 xmlSchemaValidCtxtPtr ret;
8746
8747 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
8748 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008749 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008750 return (NULL);
8751 }
8752 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
8753 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +00008754 /*
8755 * Removed due to changes of the attribute state list.
8756 /*
8757 /* ret->attrNr = 0; */
8758 /* ret->attrMax = 10; */
8759 /* ret->attrBase = NULL; */
8760 ret->attrTop = NULL;
8761 ret->attr = NULL;
8762 /*
8763 * Removed due to changes of the attribute state list.
8764 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00008765 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008766 sizeof
8767 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00008768 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008769 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
8770 free(ret);
8771 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008772 }
8773 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
Daniel Veillard3646d642004-06-02 19:19:14 +00008774 */
8775
Daniel Veillard4255d502002-04-16 15:50:10 +00008776 return (ret);
8777}
8778
8779/**
8780 * xmlSchemaFreeValidCtxt:
8781 * @ctxt: the schema validation context
8782 *
8783 * Free the resources associated to the schema validation context
8784 */
8785void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008786xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
8787{
Daniel Veillard4255d502002-04-16 15:50:10 +00008788 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008789 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008790 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00008791 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00008792 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008793 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00008794 xmlFree(ctxt);
8795}
8796
8797/**
8798 * xmlSchemaSetValidErrors:
8799 * @ctxt: a schema validation context
8800 * @err: the error function
8801 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00008802 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00008803 *
8804 * Set the error and warning callback informations
8805 */
8806void
8807xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008808 xmlSchemaValidityErrorFunc err,
8809 xmlSchemaValidityWarningFunc warn, void *ctx)
8810{
Daniel Veillard4255d502002-04-16 15:50:10 +00008811 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008812 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008813 ctxt->error = err;
8814 ctxt->warning = warn;
8815 ctxt->userData = ctx;
8816}
8817
8818/**
8819 * xmlSchemaValidateDoc:
8820 * @ctxt: a schema validation context
8821 * @doc: a parsed document tree
8822 *
8823 * Validate a document tree in memory.
8824 *
8825 * Returns 0 if the document is schemas valid, a positive error code
8826 * number otherwise and -1 in case of internal or API error.
8827 */
8828int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008829xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
8830{
Daniel Veillard4255d502002-04-16 15:50:10 +00008831 int ret;
8832
8833 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008834 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008835
8836 ctxt->doc = doc;
8837 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008838 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00008839}
8840
8841/**
8842 * xmlSchemaValidateStream:
8843 * @ctxt: a schema validation context
8844 * @input: the input to use for reading the data
8845 * @enc: an optional encoding information
8846 * @sax: a SAX handler for the resulting events
8847 * @user_data: the context to provide to the SAX handler.
8848 *
8849 * Validate a document tree in memory.
8850 *
8851 * Returns 0 if the document is schemas valid, a positive error code
8852 * number otherwise and -1 in case of internal or API error.
8853 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008854int
Daniel Veillard4255d502002-04-16 15:50:10 +00008855xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008856 xmlParserInputBufferPtr input, xmlCharEncoding enc,
8857 xmlSAXHandlerPtr sax, void *user_data)
8858{
Daniel Veillard4255d502002-04-16 15:50:10 +00008859 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008860 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008861 ctxt->input = input;
8862 ctxt->enc = enc;
8863 ctxt->sax = sax;
8864 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008865 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008866}
8867
8868#endif /* LIBXML_SCHEMAS_ENABLED */