blob: 30dba1f731de5669d7314a6f4e782180647005b8 [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
William M. Brack803812b2004-06-03 02:11:24 +0000277#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000278/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000279 * xmlSchemaPErrExt:
280 * @ctxt: the parsing context
281 * @node: the context node
282 * @error: the error code
283 * @strData1: extra data
284 * @strData2: extra data
285 * @strData3: extra data
286 * @msg: the message
287 * @str1: extra parameter for the message display
288 * @str2: extra parameter for the message display
289 * @str3: extra parameter for the message display
290 * @str4: extra parameter for the message display
291 * @str5: extra parameter for the message display
292 *
293 * Handle a parser error
294 */
295static void
296xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
297 const xmlChar * strData1, const xmlChar * strData2,
298 const xmlChar * strData3, const char *msg, const xmlChar * str1,
299 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
300 const xmlChar * str5)
301{
302
303 xmlGenericErrorFunc channel = NULL;
304 xmlStructuredErrorFunc schannel = NULL;
305 void *data = NULL;
306
307 if (ctxt != NULL) {
308 ctxt->nberrors++;
309 channel = ctxt->error;
310 data = ctxt->userData;
311 schannel = ctxt->serror;
312 }
313 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
314 error, XML_ERR_ERROR, NULL, 0,
315 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000316 (const char *) strData3, 0, 0, msg, str1, str2,
317 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000318}
William M. Brack803812b2004-06-03 02:11:24 +0000319#endif
Daniel Veillard3646d642004-06-02 19:19:14 +0000320
321/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000322 * xmlSchemaVTypeErrMemory:
323 * @node: a context node
324 * @extra: extra informations
325 *
326 * Handle an out of memory condition
327 */
328static void
329xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
330 const char *extra, xmlNodePtr node)
331{
332 if (ctxt != NULL) {
333 ctxt->nberrors++;
334 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
335 }
336 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
337 extra);
338}
339
340/**
341 * xmlSchemaVErr3:
342 * @ctxt: the validation context
343 * @node: the context node
344 * @error: the error code
345 * @msg: the error message
346 * @str1: extra data
347 * @str2: extra data
348 * @str3: extra data
349 *
350 * Handle a validation error
351 */
352static void
353xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
354 const char *msg, const xmlChar *str1, const xmlChar *str2,
355 const xmlChar *str3)
356{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000357 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000358 xmlGenericErrorFunc channel = NULL;
359 void *data = NULL;
360
361 if (ctxt != NULL) {
362 ctxt->nberrors++;
363 ctxt->err = error;
364 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000365 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000366 data = ctxt->userData;
367 }
368 /* reajust to global error numbers */
369 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000370 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000371 error, XML_ERR_ERROR, NULL, 0,
372 (const char *) str1, (const char *) str2,
373 (const char *) str3, 0, 0,
374 msg, str1, str2, str3);
375}
376/**
377 * xmlSchemaVErr:
378 * @ctxt: the validation context
379 * @node: the context node
380 * @error: the error code
381 * @msg: the error message
382 * @str1: extra data
383 * @str2: extra data
384 *
385 * Handle a validation error
386 */
387static void
388xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
389 const char *msg, const xmlChar * str1, const xmlChar * str2)
390{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000391 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000392 xmlGenericErrorFunc channel = NULL;
393 void *data = NULL;
394
395 if (ctxt != NULL) {
396 ctxt->nberrors++;
397 ctxt->err = error;
398 channel = ctxt->error;
399 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000400 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000401 }
402 /* reajust to global error numbers */
403 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000404 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000405 error, XML_ERR_ERROR, NULL, 0,
406 (const char *) str1, (const char *) str2, NULL, 0, 0,
407 msg, str1, str2);
408}
Daniel Veillard4255d502002-04-16 15:50:10 +0000409
410/************************************************************************
411 * *
412 * Allocation functions *
413 * *
414 ************************************************************************/
415
416/**
417 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +0000418 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000419 *
420 * Allocate a new Schema structure.
421 *
422 * Returns the newly allocated structure or NULL in case or error
423 */
424static xmlSchemaPtr
425xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
426{
427 xmlSchemaPtr ret;
428
429 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
430 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000431 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000432 return (NULL);
433 }
434 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000435 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000436 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000437
438 return (ret);
439}
440
441/**
442 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000443 *
444 * Allocate a new Facet structure.
445 *
446 * Returns the newly allocated structure or NULL in case or error
447 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000448xmlSchemaFacetPtr
449xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000450{
451 xmlSchemaFacetPtr ret;
452
453 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
454 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000455 return (NULL);
456 }
457 memset(ret, 0, sizeof(xmlSchemaFacet));
458
459 return (ret);
460}
461
462/**
463 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +0000464 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000465 * @node: a node
466 *
467 * Allocate a new annotation structure.
468 *
469 * Returns the newly allocated structure or NULL in case or error
470 */
471static xmlSchemaAnnotPtr
472xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
473{
474 xmlSchemaAnnotPtr ret;
475
476 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
477 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000478 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000479 return (NULL);
480 }
481 memset(ret, 0, sizeof(xmlSchemaAnnot));
482 ret->content = node;
483 return (ret);
484}
485
486/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000487 * xmlSchemaFreeAnnot:
488 * @annot: a schema type structure
489 *
490 * Deallocate a annotation structure
491 */
492static void
493xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
494{
495 if (annot == NULL)
496 return;
497 xmlFree(annot);
498}
499
500/**
Daniel Veillard1d913862003-11-21 00:28:39 +0000501 * xmlSchemaFreeImport:
502 * @import: a schema import structure
503 *
504 * Deallocate an import structure
505 */
506static void
507xmlSchemaFreeImport(xmlSchemaImportPtr import)
508{
509 if (import == NULL)
510 return;
511
512 xmlSchemaFree(import->schema);
Daniel Veillard1d913862003-11-21 00:28:39 +0000513 xmlFree(import);
514}
515
516/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000517 * xmlSchemaFreeInclude:
518 * @include: a schema include structure
519 *
520 * Deallocate an include structure
521 */
522static void
523xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
524{
525 if (include == NULL)
526 return;
527
528 xmlFreeDoc(include->doc);
529 xmlFree(include);
530}
531
532/**
533 * xmlSchemaFreeIncludeList:
534 * @includes: a schema include list
535 *
536 * Deallocate an include structure
537 */
538static void
539xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
540{
541 xmlSchemaIncludePtr next;
542
543 while (includes != NULL) {
544 next = includes->next;
545 xmlSchemaFreeInclude(includes);
546 includes = next;
547 }
548}
549
550/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000551 * xmlSchemaFreeNotation:
552 * @schema: a schema notation structure
553 *
554 * Deallocate a Schema Notation structure.
555 */
556static void
557xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
558{
559 if (nota == NULL)
560 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000561 xmlFree(nota);
562}
563
564/**
565 * xmlSchemaFreeAttribute:
566 * @schema: a schema attribute structure
567 *
568 * Deallocate a Schema Attribute structure.
569 */
570static void
571xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
572{
573 if (attr == NULL)
574 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000575 xmlFree(attr);
576}
577
578/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000579 * xmlSchemaFreeWildcardNsSet:
580 * set: a schema wildcard namespace
581 *
582 * Deallocate a list of wildcard constraint structures.
583 */
584static void
585xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
586{
587 xmlSchemaWildcardNsPtr next;
588
589 while (set != NULL) {
590 next = set->next;
591 xmlFree(set);
592 set = next;
593 }
594}
595
596/**
597 * xmlSchemaFreeWildcard:
598 * @schema: a schema attribute group structure
599 *
600 * Deallocate a Schema Attribute Group structure.
601 */
602static void
603xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
604{
605 if (wildcard == NULL)
606 return;
607 if (wildcard->annot != NULL)
608 xmlSchemaFreeAnnot(wildcard->annot);
609 if (wildcard->nsSet != NULL)
610 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
611 if (wildcard->negNsSet != NULL)
612 xmlFree(wildcard->negNsSet);
613 xmlFree(wildcard);
614}
615
616/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000617 * xmlSchemaFreeAttributeGroup:
618 * @schema: a schema attribute group structure
619 *
620 * Deallocate a Schema Attribute Group structure.
621 */
622static void
623xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
624{
625 if (attr == NULL)
626 return;
Daniel Veillard3646d642004-06-02 19:19:14 +0000627 if (attr->annot != NULL)
628 xmlSchemaFreeAnnot(attr->annot);
629 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
630 (attr->attributeWildcard != NULL))
631 xmlSchemaFreeWildcard(attr->attributeWildcard);
632
Daniel Veillard4255d502002-04-16 15:50:10 +0000633 xmlFree(attr);
634}
635
636/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000637 * xmlSchemaFreeAttributeUseList:
638 * @attrUse: a schema attribute link structure
639 *
640 * Deallocate a list of schema attribute uses.
641 */
642static void
643xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
644{
645 xmlSchemaAttributeLinkPtr next;
646
647 while (attrUse != NULL) {
648 next = attrUse->next;
649 xmlFree(attrUse);
650 attrUse = next;
651 }
652}
653
654/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000655 * xmlSchemaFreeElement:
656 * @schema: a schema element structure
657 *
658 * Deallocate a Schema Element structure.
659 */
660static void
661xmlSchemaFreeElement(xmlSchemaElementPtr elem)
662{
663 if (elem == NULL)
664 return;
Daniel Veillard32370232002-10-16 14:08:14 +0000665 if (elem->annot != NULL)
666 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000667 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000668 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000669 xmlFree(elem);
670}
671
672/**
673 * xmlSchemaFreeFacet:
674 * @facet: a schema facet structure
675 *
676 * Deallocate a Schema Facet structure.
677 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000678void
Daniel Veillard4255d502002-04-16 15:50:10 +0000679xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
680{
681 if (facet == NULL)
682 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000683 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000684 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000685 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000686 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000687 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000688 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000689 xmlFree(facet);
690}
691
692/**
693 * xmlSchemaFreeType:
694 * @type: a schema type structure
695 *
696 * Deallocate a Schema Type structure.
697 */
698void
699xmlSchemaFreeType(xmlSchemaTypePtr type)
700{
701 if (type == NULL)
702 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000703 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000704 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000705 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000706 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000707
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000708 facet = type->facets;
709 while (facet != NULL) {
710 next = facet->next;
711 xmlSchemaFreeFacet(facet);
712 facet = next;
713 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000714 }
Daniel Veillard3646d642004-06-02 19:19:14 +0000715 if (type->type != XML_SCHEMA_TYPE_BASIC) {
716 if (type->attributeUses != NULL)
717 xmlSchemaFreeAttributeUseList(type->attributeUses);
718 if ((type->attributeWildcard != NULL) &&
719 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
720 ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
721 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)))) {
722 xmlSchemaFreeWildcard(type->attributeWildcard);
723 }
724 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000725 xmlFree(type);
726}
727
728/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000729 * xmlSchemaFreeTypeList:
730 * @type: a schema type structure
731 *
732 * Deallocate a Schema Type structure.
733 */
734static void
735xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
736{
737 xmlSchemaTypePtr next;
738
739 while (type != NULL) {
740 next = type->redef;
741 xmlSchemaFreeType(type);
742 type = next;
743 }
744}
745
746/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000747 * xmlSchemaFree:
748 * @schema: a schema structure
749 *
750 * Deallocate a Schema structure.
751 */
752void
753xmlSchemaFree(xmlSchemaPtr schema)
754{
755 if (schema == NULL)
756 return;
757
Daniel Veillard4255d502002-04-16 15:50:10 +0000758 if (schema->notaDecl != NULL)
759 xmlHashFree(schema->notaDecl,
760 (xmlHashDeallocator) xmlSchemaFreeNotation);
761 if (schema->attrDecl != NULL)
762 xmlHashFree(schema->attrDecl,
763 (xmlHashDeallocator) xmlSchemaFreeAttribute);
764 if (schema->attrgrpDecl != NULL)
765 xmlHashFree(schema->attrgrpDecl,
766 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
767 if (schema->elemDecl != NULL)
768 xmlHashFree(schema->elemDecl,
769 (xmlHashDeallocator) xmlSchemaFreeElement);
770 if (schema->typeDecl != NULL)
771 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000772 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000773 if (schema->groupDecl != NULL)
774 xmlHashFree(schema->groupDecl,
775 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +0000776 if (schema->schemasImports != NULL)
777 xmlHashFree(schema->schemasImports,
778 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000779 if (schema->includes != NULL) {
780 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
781 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000782 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000783 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +0000784 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000785 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000786 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000787
788 xmlFree(schema);
789}
790
791/************************************************************************
792 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000793 * Debug functions *
794 * *
795 ************************************************************************/
796
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000797#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000798
Daniel Veillard4255d502002-04-16 15:50:10 +0000799/**
800 * xmlSchemaElementDump:
801 * @elem: an element
802 * @output: the file output
803 *
804 * Dump the element
805 */
806static void
807xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000808 const xmlChar * name ATTRIBUTE_UNUSED,
809 const xmlChar * context ATTRIBUTE_UNUSED,
810 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000811{
812 if (elem == NULL)
813 return;
814
815 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +0000816 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
817 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000818 fprintf(output, ": %s ", elem->name);
819 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000820 fprintf(output, "namespace '%s' ", namespace);
821
Daniel Veillard4255d502002-04-16 15:50:10 +0000822 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000823 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000824 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000825 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000826 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000827 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000828 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000829 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000830 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000831 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000832 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000833 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000834 fprintf(output, "\n");
835 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000836 fprintf(output, " ");
837 if (elem->minOccurs != 1)
838 fprintf(output, "min: %d ", elem->minOccurs);
839 if (elem->maxOccurs >= UNBOUNDED)
840 fprintf(output, "max: unbounded\n");
841 else if (elem->maxOccurs != 1)
842 fprintf(output, "max: %d\n", elem->maxOccurs);
843 else
844 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000845 }
846 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000847 fprintf(output, " type: %s", elem->namedType);
848 if (elem->namedTypeNs != NULL)
849 fprintf(output, " ns %s\n", elem->namedTypeNs);
850 else
851 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000852 }
853 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000854 fprintf(output, " substitutionGroup: %s", elem->substGroup);
855 if (elem->substGroupNs != NULL)
856 fprintf(output, " ns %s\n", elem->substGroupNs);
857 else
858 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000859 }
860 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000861 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000862}
863
864/**
865 * xmlSchemaAnnotDump:
866 * @output: the file output
867 * @annot: a annotation
868 *
869 * Dump the annotation
870 */
871static void
872xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
873{
874 xmlChar *content;
875
876 if (annot == NULL)
877 return;
878
879 content = xmlNodeGetContent(annot->content);
880 if (content != NULL) {
881 fprintf(output, " Annot: %s\n", content);
882 xmlFree(content);
883 } else
884 fprintf(output, " Annot: empty\n");
885}
886
887/**
888 * xmlSchemaTypeDump:
889 * @output: the file output
890 * @type: a type structure
891 *
892 * Dump a SchemaType structure
893 */
894static void
895xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
896{
897 if (type == NULL) {
898 fprintf(output, "Type: NULL\n");
899 return;
900 }
901 fprintf(output, "Type: ");
902 if (type->name != NULL)
903 fprintf(output, "%s, ", type->name);
904 else
905 fprintf(output, "no name");
906 switch (type->type) {
907 case XML_SCHEMA_TYPE_BASIC:
908 fprintf(output, "basic ");
909 break;
910 case XML_SCHEMA_TYPE_SIMPLE:
911 fprintf(output, "simple ");
912 break;
913 case XML_SCHEMA_TYPE_COMPLEX:
914 fprintf(output, "complex ");
915 break;
916 case XML_SCHEMA_TYPE_SEQUENCE:
917 fprintf(output, "sequence ");
918 break;
919 case XML_SCHEMA_TYPE_CHOICE:
920 fprintf(output, "choice ");
921 break;
922 case XML_SCHEMA_TYPE_ALL:
923 fprintf(output, "all ");
924 break;
925 case XML_SCHEMA_TYPE_UR:
926 fprintf(output, "ur ");
927 break;
928 case XML_SCHEMA_TYPE_RESTRICTION:
929 fprintf(output, "restriction ");
930 break;
931 case XML_SCHEMA_TYPE_EXTENSION:
932 fprintf(output, "extension ");
933 break;
934 default:
935 fprintf(output, "unknowntype%d ", type->type);
936 break;
937 }
938 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000939 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000940 }
941 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000942 case XML_SCHEMA_CONTENT_UNKNOWN:
943 fprintf(output, "unknown ");
944 break;
945 case XML_SCHEMA_CONTENT_EMPTY:
946 fprintf(output, "empty ");
947 break;
948 case XML_SCHEMA_CONTENT_ELEMENTS:
949 fprintf(output, "element ");
950 break;
951 case XML_SCHEMA_CONTENT_MIXED:
952 fprintf(output, "mixed ");
953 break;
954 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
955 fprintf(output, "mixed_or_elems ");
956 break;
957 case XML_SCHEMA_CONTENT_BASIC:
958 fprintf(output, "basic ");
959 break;
960 case XML_SCHEMA_CONTENT_SIMPLE:
961 fprintf(output, "simple ");
962 break;
963 case XML_SCHEMA_CONTENT_ANY:
964 fprintf(output, "any ");
965 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000966 }
967 fprintf(output, "\n");
968 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000969 fprintf(output, " ");
970 if (type->minOccurs != 1)
971 fprintf(output, "min: %d ", type->minOccurs);
972 if (type->maxOccurs >= UNBOUNDED)
973 fprintf(output, "max: unbounded\n");
974 else if (type->maxOccurs != 1)
975 fprintf(output, "max: %d\n", type->maxOccurs);
976 else
977 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000978 }
979 if (type->annot != NULL)
980 xmlSchemaAnnotDump(output, type->annot);
981 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000982 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000983
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000984 fprintf(output, " subtypes: ");
985 while (sub != NULL) {
986 fprintf(output, "%s ", sub->name);
987 sub = sub->next;
988 }
989 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000990 }
991
992}
993
994/**
995 * xmlSchemaDump:
996 * @output: the file output
997 * @schema: a schema structure
998 *
999 * Dump a Schema structure.
1000 */
1001void
1002xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
1003{
1004 if (schema == NULL) {
1005 fprintf(output, "Schemas: NULL\n");
1006 return;
1007 }
1008 fprintf(output, "Schemas: ");
1009 if (schema->name != NULL)
1010 fprintf(output, "%s, ", schema->name);
1011 else
1012 fprintf(output, "no name, ");
1013 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001014 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001015 else
1016 fprintf(output, "no target namespace");
1017 fprintf(output, "\n");
1018 if (schema->annot != NULL)
1019 xmlSchemaAnnotDump(output, schema->annot);
1020
1021 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
1022 output);
1023 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001024 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00001025}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001026#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00001027
1028/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001029 * *
1030 * Utilities *
1031 * *
1032 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001033
1034/**
1035 * xmlSchemaGetProp:
1036 * @ctxt: the parser context
1037 * @node: the node
1038 * @name: the property name
1039 *
1040 * Read a attribute value and internalize the string
1041 *
1042 * Returns the string or NULL if not present.
1043 */
1044static const xmlChar *
1045xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1046 const char *name)
1047{
1048 xmlChar *val;
1049 const xmlChar *ret;
1050
1051 val = xmlGetProp(node, BAD_CAST name);
1052 if (val == NULL)
1053 return(NULL);
1054 ret = xmlDictLookup(ctxt->dict, val, -1);
1055 xmlFree(val);
1056 return(ret);
1057}
1058
William M. Brack29aa7722004-05-12 00:27:56 +00001059#if 0
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001060/**
1061 * xmlSchemaGetNamespace:
1062 * @ctxt: the parser context
1063 * @schema: the schemas containing the declaration
1064 * @node: the node
1065 * @qname: the QName to analyze
1066 *
1067 * Find the namespace name for the given declaration.
1068 *
1069 * Returns the local name for that declaration, as well as the namespace name
William M. Bracke7091952004-05-11 15:09:58 +00001070 * NOTE: This function is no longer used (Buchcik, May '04)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001071 */
1072static const xmlChar *
1073xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1074 xmlNodePtr node, const xmlChar *qname,
1075 const xmlChar **namespace) {
1076 int len;
1077 const xmlChar *name, *prefix, *def = NULL;
1078 xmlNsPtr ns;
1079
1080 *namespace = NULL;
1081
William M. Bracke7091952004-05-11 15:09:58 +00001082 /* TODO: The following seems to be not correct here:
1083 * 1. The name of a declaration is a NCName, not a QName.
1084 * 2. The attribute "targetNamespace" is allowed for the
1085 * <schema> Element Information Item only.
1086 * 3. One cannot evaluate the target namespace, by the type
1087 * of declaration, since it is dependant on the xxxFormDefault
1088 * of <schema> and the form attribute of an <element> or <attribute>.
1089 */
1090
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001091 if (xmlStrEqual(node->name, BAD_CAST "element") ||
1092 xmlStrEqual(node->name, BAD_CAST "attribute") ||
1093 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
1094 xmlStrEqual(node->name, BAD_CAST "complexType")) {
1095 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
1096 }
1097
William M. Bracke7091952004-05-11 15:09:58 +00001098
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001099 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
1100 name = xmlSplitQName3(qname, &len);
1101 if (name == NULL) {
1102 if (def == NULL) {
1103 if (xmlStrEqual(node->name, BAD_CAST "element")) {
1104 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
1105 *namespace = schema->targetNamespace;
1106 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
1107 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
1108 *namespace = schema->targetNamespace;
1109 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
1110 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
1111 *namespace = schema->targetNamespace;
1112 }
1113 } else {
1114 *namespace = def;
1115 }
1116 return(qname);
1117 }
William M. Bracke7091952004-05-11 15:09:58 +00001118
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001119 name = xmlDictLookup(ctxt->dict, name, -1);
1120 prefix = xmlDictLookup(ctxt->dict, qname, len);
1121 if (def != NULL) {
1122 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
1123 "%s: presence of both prefix %s and targetNamespace\n",
1124 node->name, prefix);
1125 }
1126 ns = xmlSearchNs(node->doc, node, prefix);
1127 if (ns == NULL) {
1128 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1129 "%s: the QName prefix %s is undefined\n",
1130 node->name, prefix);
1131 return(name);
1132 }
1133 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1134 return(name);
1135}
William M. Brack29aa7722004-05-12 00:27:56 +00001136#endif
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001137
1138/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00001139 * *
1140 * Parsing functions *
1141 * *
1142 ************************************************************************/
1143
1144/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001145 * xmlSchemaGetElem:
1146 * @schema: the schemas context
1147 * @name: the element name
1148 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001149 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001150 *
1151 * Lookup a an element in the schemas or the accessible schemas
1152 *
1153 * Returns the element definition or NULL if not found.
1154 */
1155static xmlSchemaElementPtr
1156xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001157 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001158{
1159 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001160 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001161
1162 if ((name == NULL) || (schema == NULL))
1163 return (NULL);
1164
Daniel Veillard3646d642004-06-02 19:19:14 +00001165
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001166 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001167 if ((ret != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00001168 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_GLOBAL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001169 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00001170 } else
1171 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00001172 /*
1173 * This one was removed, since top level element declarations have
1174 * the target namespace specified in targetNamespace of the <schema>
1175 * information element, even if elementFormDefault is "unqualified".
1176 */
1177
1178 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001179 if (xmlStrEqual(namespace, schema->targetNamespace))
1180 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1181 else
1182 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001183 if ((ret != NULL) &&
1184 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001185 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001186 }
William M. Bracke7091952004-05-11 15:09:58 +00001187 */
Daniel Veillard3646d642004-06-02 19:19:14 +00001188
1189 /* if (level > 0) */
1190 if (namespace == NULL)
1191 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1192 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001193 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001194 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00001195 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00001196 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
1197 return (ret);
1198 } else
1199 ret = NULL;
1200 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001201#ifdef DEBUG
1202 if (ret == NULL) {
1203 if (namespace == NULL)
1204 fprintf(stderr, "Unable to lookup type %s", name);
1205 else
1206 fprintf(stderr, "Unable to lookup type %s:%s", name,
1207 namespace);
1208 }
1209#endif
1210 return (ret);
1211}
1212
1213/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001214 * xmlSchemaGetType:
1215 * @schema: the schemas context
1216 * @name: the type name
1217 * @ns: the type namespace
1218 *
1219 * Lookup a type in the schemas or the predefined types
1220 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001221 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001222 */
1223static xmlSchemaTypePtr
1224xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001225 const xmlChar * namespace)
1226{
Daniel Veillard4255d502002-04-16 15:50:10 +00001227 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001228 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001229
1230 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001231 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001232 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001233 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001234 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001235 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001236 }
1237 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001238 if (ret != NULL)
1239 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00001240 if (namespace == NULL)
1241 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1242 else
Daniel Veillard1d913862003-11-21 00:28:39 +00001243 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001244 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00001245 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001246 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1247 return (ret);
1248 } else
1249 ret = NULL;
1250 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001251#ifdef DEBUG
1252 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001253 if (namespace == NULL)
1254 fprintf(stderr, "Unable to lookup type %s", name);
1255 else
1256 fprintf(stderr, "Unable to lookup type %s:%s", name,
1257 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001258 }
1259#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001260 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001261}
1262
Daniel Veillard3646d642004-06-02 19:19:14 +00001263/**
1264 * xmlSchemaGetAttribute:
1265 * @schema: the context of the schema
1266 * @name: the name of the attribute
1267 * @ns: the target namespace of the attribute
1268 *
1269 * Lookup a an attribute in the schema or imported schemas
1270 *
1271 * Returns the attribute declaration or NULL if not found.
1272 */
1273static xmlSchemaAttributePtr
1274xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
1275 const xmlChar * namespace)
1276{
1277 xmlSchemaAttributePtr ret;
1278 xmlSchemaImportPtr import = NULL;
1279
1280 if ((name == NULL) || (schema == NULL))
1281 return (NULL);
1282
1283
1284 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
1285 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
1286 return (ret);
1287 else
1288 ret = NULL;
1289 if (namespace == NULL)
1290 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1291 else
1292 import = xmlHashLookup(schema->schemasImports, namespace);
1293 if (import != NULL) {
1294 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
1295 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
1296 return (ret);
1297 } else
1298 ret = NULL;
1299 }
1300#ifdef DEBUG
1301 if (ret == NULL) {
1302 if (namespace == NULL)
1303 fprintf(stderr, "Unable to lookup attribute %s", name);
1304 else
1305 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
1306 namespace);
1307 }
1308#endif
1309 return (ret);
1310}
1311
1312/**
1313 * xmlSchemaGetAttributeGroup:
1314 * @schema: the context of the schema
1315 * @name: the name of the attribute group
1316 * @ns: the target namespace of the attribute group
1317 *
1318 * Lookup a an attribute group in the schema or imported schemas
1319 *
1320 * Returns the attribute group definition or NULL if not found.
1321 */
1322static xmlSchemaAttributeGroupPtr
1323xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
1324 const xmlChar * namespace)
1325{
1326 xmlSchemaAttributeGroupPtr ret;
1327 xmlSchemaImportPtr import = NULL;
1328
1329 if ((name == NULL) || (schema == NULL))
1330 return (NULL);
1331
1332
1333 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
1334 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
1335 return (ret);
1336 else
1337 ret = NULL;
1338 if (namespace == NULL)
1339 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1340 else
1341 import = xmlHashLookup(schema->schemasImports, namespace);
1342 if (import != NULL) {
1343 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
1344 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
1345 return (ret);
1346 else
1347 ret = NULL;
1348 }
1349#ifdef DEBUG
1350 if (ret == NULL) {
1351 if (namespace == NULL)
1352 fprintf(stderr, "Unable to lookup attribute group %s", name);
1353 else
1354 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
1355 namespace);
1356 }
1357#endif
1358 return (ret);
1359}
1360
1361/**
1362 * xmlSchemaGetGroup:
1363 * @schema: the context of the schema
1364 * @name: the name of the group
1365 * @ns: the target namespace of the group
1366 *
1367 * Lookup a group in the schema or imported schemas
1368 *
1369 * Returns the group definition or NULL if not found.
1370 */
1371static xmlSchemaTypePtr
1372xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
1373 const xmlChar * namespace)
1374{
1375 xmlSchemaTypePtr ret;
1376 xmlSchemaImportPtr import = NULL;
1377
1378 if ((name == NULL) || (schema == NULL))
1379 return (NULL);
1380
1381
1382 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
1383 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
1384 return (ret);
1385 else
1386 ret = NULL;
1387 if (namespace == NULL)
1388 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1389 else
1390 import = xmlHashLookup(schema->schemasImports, namespace);
1391 if (import != NULL) {
1392 ret = xmlSchemaGetGroup(import->schema, name, namespace);
1393 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
1394 return (ret);
1395 else
1396 ret = NULL;
1397 }
1398#ifdef DEBUG
1399 if (ret == NULL) {
1400 if (namespace == NULL)
1401 fprintf(stderr, "Unable to lookup group %s", name);
1402 else
1403 fprintf(stderr, "Unable to lookup group %s:%s", name,
1404 namespace);
1405 }
1406#endif
1407 return (ret);
1408}
1409
Daniel Veillard4255d502002-04-16 15:50:10 +00001410/************************************************************************
1411 * *
1412 * Parsing functions *
1413 * *
1414 ************************************************************************/
1415
1416#define IS_BLANK_NODE(n) \
1417 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1418
1419/**
1420 * xmlSchemaIsBlank:
1421 * @str: a string
1422 *
1423 * Check if a string is ignorable
1424 *
1425 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1426 */
1427static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001428xmlSchemaIsBlank(xmlChar * str)
1429{
Daniel Veillard4255d502002-04-16 15:50:10 +00001430 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001431 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001432 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001433 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001434 return (0);
1435 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001436 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001437 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001438}
1439
1440/**
1441 * xmlSchemaAddNotation:
1442 * @ctxt: a schema validation context
1443 * @schema: the schema being built
1444 * @name: the item name
1445 *
1446 * Add an XML schema Attrribute declaration
1447 * *WARNING* this interface is highly subject to change
1448 *
1449 * Returns the new struture or NULL in case of error
1450 */
1451static xmlSchemaNotationPtr
1452xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001453 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001454{
1455 xmlSchemaNotationPtr ret = NULL;
1456 int val;
1457
1458 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1459 return (NULL);
1460
1461 if (schema->notaDecl == NULL)
1462 schema->notaDecl = xmlHashCreate(10);
1463 if (schema->notaDecl == NULL)
1464 return (NULL);
1465
1466 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1467 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001468 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001469 return (NULL);
1470 }
1471 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001472 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001473 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1474 ret);
1475 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001476 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1477 XML_SCHEMAP_REDEFINED_NOTATION,
1478 "Notation %s already defined\n",
1479 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001480 xmlFree(ret);
1481 return (NULL);
1482 }
1483 return (ret);
1484}
1485
1486
1487/**
1488 * xmlSchemaAddAttribute:
1489 * @ctxt: a schema validation context
1490 * @schema: the schema being built
1491 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001492 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001493 *
1494 * Add an XML schema Attrribute declaration
1495 * *WARNING* this interface is highly subject to change
1496 *
1497 * Returns the new struture or NULL in case of error
1498 */
1499static xmlSchemaAttributePtr
1500xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001501 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001502{
1503 xmlSchemaAttributePtr ret = NULL;
1504 int val;
1505
1506 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1507 return (NULL);
1508
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001509#ifdef DEBUG
1510 fprintf(stderr, "Adding attribute %s\n", name);
1511 if (namespace != NULL)
1512 fprintf(stderr, " target namespace %s\n", namespace);
1513#endif
1514
Daniel Veillard4255d502002-04-16 15:50:10 +00001515 if (schema->attrDecl == NULL)
1516 schema->attrDecl = xmlHashCreate(10);
1517 if (schema->attrDecl == NULL)
1518 return (NULL);
1519
1520 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1521 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001522 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001523 return (NULL);
1524 }
1525 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001526 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1527 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001528 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001529 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001530 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001531 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1532 XML_SCHEMAP_REDEFINED_ATTR,
1533 "Attribute %s already defined\n",
1534 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001535 xmlFree(ret);
1536 return (NULL);
1537 }
1538 return (ret);
1539}
1540
1541/**
1542 * xmlSchemaAddAttributeGroup:
1543 * @ctxt: a schema validation context
1544 * @schema: the schema being built
1545 * @name: the item name
1546 *
1547 * Add an XML schema Attrribute Group declaration
1548 *
1549 * Returns the new struture or NULL in case of error
1550 */
1551static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001552xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1553 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001554{
1555 xmlSchemaAttributeGroupPtr ret = NULL;
1556 int val;
1557
1558 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1559 return (NULL);
1560
1561 if (schema->attrgrpDecl == NULL)
1562 schema->attrgrpDecl = xmlHashCreate(10);
1563 if (schema->attrgrpDecl == NULL)
1564 return (NULL);
1565
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001566 ret =
1567 (xmlSchemaAttributeGroupPtr)
1568 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001569 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001570 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001571 return (NULL);
1572 }
1573 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001574 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001575 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001576 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001577 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001578 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1579 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1580 "Attribute group %s already defined\n",
1581 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001582 xmlFree(ret);
1583 return (NULL);
1584 }
1585 return (ret);
1586}
1587
1588/**
1589 * xmlSchemaAddElement:
1590 * @ctxt: a schema validation context
1591 * @schema: the schema being built
1592 * @name: the type name
1593 * @namespace: the type namespace
1594 *
1595 * Add an XML schema Element declaration
1596 * *WARNING* this interface is highly subject to change
1597 *
1598 * Returns the new struture or NULL in case of error
1599 */
1600static xmlSchemaElementPtr
1601xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1602 const xmlChar * name, const xmlChar * namespace)
1603{
1604 xmlSchemaElementPtr ret = NULL;
1605 int val;
1606
1607 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1608 return (NULL);
1609
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001610#ifdef DEBUG
1611 fprintf(stderr, "Adding element %s\n", name);
1612 if (namespace != NULL)
1613 fprintf(stderr, " target namespace %s\n", namespace);
1614#endif
1615
Daniel Veillard4255d502002-04-16 15:50:10 +00001616 if (schema->elemDecl == NULL)
1617 schema->elemDecl = xmlHashCreate(10);
1618 if (schema->elemDecl == NULL)
1619 return (NULL);
1620
1621 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1622 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001623 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001624 return (NULL);
1625 }
1626 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001627 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1628 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001629 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001630 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001631 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001632 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001633
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001634 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001635 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1636 namespace, ret);
1637 if (val != 0) {
1638 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1639 XML_SCHEMAP_REDEFINED_ELEMENT,
1640 "Element %s already defined\n",
1641 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001642 xmlFree(ret);
1643 return (NULL);
1644 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001645 }
1646 return (ret);
1647}
1648
1649/**
1650 * xmlSchemaAddType:
1651 * @ctxt: a schema validation context
1652 * @schema: the schema being built
1653 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001654 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001655 *
1656 * Add an XML schema Simple Type definition
1657 * *WARNING* this interface is highly subject to change
1658 *
1659 * Returns the new struture or NULL in case of error
1660 */
1661static xmlSchemaTypePtr
1662xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001663 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001664{
1665 xmlSchemaTypePtr ret = NULL;
1666 int val;
1667
1668 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1669 return (NULL);
1670
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001671#ifdef DEBUG
1672 fprintf(stderr, "Adding type %s\n", name);
1673 if (namespace != NULL)
1674 fprintf(stderr, " target namespace %s\n", namespace);
1675#endif
1676
Daniel Veillard4255d502002-04-16 15:50:10 +00001677 if (schema->typeDecl == NULL)
1678 schema->typeDecl = xmlHashCreate(10);
1679 if (schema->typeDecl == NULL)
1680 return (NULL);
1681
1682 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1683 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001684 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001685 return (NULL);
1686 }
1687 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001688 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001689 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001690 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001691 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001692 if (ctxt->includes == 0) {
1693 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1694 XML_SCHEMAP_REDEFINED_TYPE,
1695 "Type %s already defined\n",
1696 name, NULL);
1697 xmlFree(ret);
1698 return (NULL);
1699 } else {
1700 xmlSchemaTypePtr prev;
1701
1702 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1703 if (prev == NULL) {
1704 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1705 XML_ERR_INTERNAL_ERROR,
1706 "Internal error on type %s definition\n",
1707 name, NULL);
1708 xmlFree(ret);
1709 return (NULL);
1710 }
1711 ret->redef = prev->redef;
1712 prev->redef = ret;
1713 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001714 }
1715 ret->minOccurs = 1;
1716 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00001717 ret->attributeUses = NULL;
1718 ret->attributeWildcard = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001719
1720 return (ret);
1721}
1722
1723/**
1724 * xmlSchemaAddGroup:
1725 * @ctxt: a schema validation context
1726 * @schema: the schema being built
1727 * @name: the group name
1728 *
1729 * Add an XML schema Group definition
1730 *
1731 * Returns the new struture or NULL in case of error
1732 */
1733static xmlSchemaTypePtr
1734xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001735 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001736{
1737 xmlSchemaTypePtr ret = NULL;
1738 int val;
1739
1740 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1741 return (NULL);
1742
1743 if (schema->groupDecl == NULL)
1744 schema->groupDecl = xmlHashCreate(10);
1745 if (schema->groupDecl == NULL)
1746 return (NULL);
1747
1748 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1749 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001750 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001751 return (NULL);
1752 }
1753 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001754 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001755 val =
1756 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1757 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001758 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001759 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1760 XML_SCHEMAP_REDEFINED_GROUP,
1761 "Group %s already defined\n",
1762 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001763 xmlFree(ret);
1764 return (NULL);
1765 }
1766 ret->minOccurs = 1;
1767 ret->maxOccurs = 1;
1768
1769 return (ret);
1770}
1771
Daniel Veillard3646d642004-06-02 19:19:14 +00001772/**
1773 * xmlSchemaNewWildcardNs:
1774 * @ctxt: a schema validation context
1775 *
1776 * Creates a new wildcard namespace constraint.
1777 *
1778 * Returns the new struture or NULL in case of error
1779 */
1780static xmlSchemaWildcardNsPtr
1781xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
1782{
1783 xmlSchemaWildcardNsPtr ret;
1784
1785 ret = (xmlSchemaWildcardNsPtr)
1786 xmlMalloc(sizeof(xmlSchemaWildcardNs));
1787 if (ret == NULL) {
1788 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
1789 return (NULL);
1790 }
1791 ret->value = NULL;
1792 ret->next = NULL;
1793 return (ret);
1794}
1795
1796/**
1797 * xmlSchemaAddWildcard:
1798 * @ctxt: a schema validation context
1799 * @schema: the schema being built
1800 * @name: the group name
1801 *
1802 * Add an XML schema Group definition
1803 *
1804 * Returns the new struture or NULL in case of error
1805 */
1806static xmlSchemaWildcardPtr
1807xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
1808{
1809 xmlSchemaWildcardPtr ret = NULL;
1810
1811 if (ctxt == NULL)
1812 return (NULL);
1813
1814 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
1815 if (ret == NULL) {
1816 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
1817 return (NULL);
1818 }
1819 memset(ret, 0, sizeof(xmlSchemaWildcard));
1820 ret->minOccurs = 1;
1821 ret->maxOccurs = 1;
1822
1823 return (ret);
1824}
1825
Daniel Veillard4255d502002-04-16 15:50:10 +00001826/************************************************************************
1827 * *
1828 * Utilities for parsing *
1829 * *
1830 ************************************************************************/
1831
1832/**
1833 * xmlGetQNameProp:
1834 * @ctxt: a schema validation context
1835 * @node: a subtree containing XML Schema informations
1836 * @name: the attribute name
1837 * @namespace: the result namespace if any
1838 *
1839 * Extract a QName Attribute value
1840 *
1841 * Returns the NCName or NULL if not found, and also update @namespace
1842 * with the namespace URI
1843 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001844static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001845xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001846 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001847{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001848 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001849 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001850 const xmlChar *ret, *prefix;
1851 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001852
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001853 *namespace = NULL;
1854 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001855 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001856 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001857
Daniel Veillardba0153a2004-04-01 10:42:31 +00001858 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00001859 ns = xmlSearchNs(node->doc, node, 0);
1860 if (ns) {
1861 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1862 return (val);
1863 }
1864 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001865 ret = xmlSplitQName3(val, &len);
1866 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001867 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001868 }
1869 ret = xmlDictLookup(ctxt->dict, ret, -1);
1870 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001871
1872 ns = xmlSearchNs(node->doc, node, prefix);
1873 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001874 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1875 "Attribute %s: the QName prefix %s is undefined\n",
1876 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001877 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001878 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001879 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001880 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001881}
1882
1883/**
1884 * xmlGetMaxOccurs:
1885 * @ctxt: a schema validation context
1886 * @node: a subtree containing XML Schema informations
1887 *
1888 * Get the maxOccurs property
1889 *
1890 * Returns the default if not found, or the value
1891 */
1892static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001893xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1894{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001895 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001896 int ret = 0;
1897
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001898 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001899 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001900 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001901
1902 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001903 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001904 }
1905
1906 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001907 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001908 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001909 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001910 ret = ret * 10 + (*cur - '0');
1911 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001912 }
William M. Brack76e95df2003-10-18 16:20:14 +00001913 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001914 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001915 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001916 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1917 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001918 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001919 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001920 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001921}
1922
1923/**
1924 * xmlGetMinOccurs:
1925 * @ctxt: a schema validation context
1926 * @node: a subtree containing XML Schema informations
1927 *
1928 * Get the minOccurs property
1929 *
1930 * Returns the default if not found, or the value
1931 */
1932static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001933xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1934{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001935 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001936 int ret = 0;
1937
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001938 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001939 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001940 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001941
1942 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001943 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001944 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001945 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001946 ret = ret * 10 + (*cur - '0');
1947 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001948 }
William M. Brack76e95df2003-10-18 16:20:14 +00001949 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001950 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001951 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001952 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1953 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001954 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001955 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001956 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001957}
1958
1959/**
1960 * xmlGetBooleanProp:
1961 * @ctxt: a schema validation context
1962 * @node: a subtree containing XML Schema informations
1963 * @name: the attribute name
1964 * @def: the default value
1965 *
1966 * Get is a bolean property is set
1967 *
1968 * Returns the default if not found, 0 if found to be false,
1969 * 1 if found to be true
1970 */
1971static int
1972xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001973 const char *name, int def)
1974{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001975 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001976
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001977 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001978 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001979 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001980
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001981 if (xmlStrEqual(val, BAD_CAST "true"))
1982 def = 1;
1983 else if (xmlStrEqual(val, BAD_CAST "false"))
1984 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001985 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001986 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1987 "Attribute %s: the value %s is not boolean\n",
1988 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001989 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001990 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001991}
1992
1993/************************************************************************
1994 * *
1995 * Shema extraction from an Infoset *
1996 * *
1997 ************************************************************************/
1998static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1999 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00002000 xmlNodePtr node,
2001 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002002static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
2003 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00002004 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00002005 xmlNodePtr node,
2006 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002007static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
2008 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00002009 xmlSchemaPtr schema,
2010 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002011 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00002012static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
2013 xmlSchemaPtr schema,
2014 xmlNodePtr node);
2015static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
2016 xmlSchemaPtr schema,
2017 xmlNodePtr node);
2018static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
2019 ctxt,
2020 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002021 xmlNodePtr node,
2022 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002023static xmlSchemaAttributeGroupPtr
2024xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00002025 xmlSchemaPtr schema, xmlNodePtr node,
2026 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002027static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
2028 xmlSchemaPtr schema,
2029 xmlNodePtr node);
2030static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
2031 xmlSchemaPtr schema,
2032 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00002033static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002034xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
2035 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002036
2037/**
2038 * xmlSchemaParseAttrDecls:
2039 * @ctxt: a schema validation context
2040 * @schema: the schema being built
2041 * @node: a subtree containing XML Schema informations
2042 * @type: the hosting type
2043 *
2044 * parse a XML schema attrDecls declaration corresponding to
2045 * <!ENTITY % attrDecls
2046 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
2047 */
2048static xmlNodePtr
2049xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2050 xmlNodePtr child, xmlSchemaTypePtr type)
2051{
2052 xmlSchemaAttributePtr lastattr, attr;
2053
2054 lastattr = NULL;
2055 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002056 (IS_SCHEMA(child, "attributeGroup"))) {
2057 attr = NULL;
2058 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00002059 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002060 } else if (IS_SCHEMA(child, "attributeGroup")) {
2061 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00002062 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002063 }
2064 if (attr != NULL) {
2065 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002066 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
2067 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
2068 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002069 type->attributes = attr;
2070 lastattr = attr;
2071 } else {
2072 lastattr->next = attr;
2073 lastattr = attr;
2074 }
2075 }
2076 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002077 }
2078 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002079 xmlSchemaWildcardPtr wildcard;
2080
2081 wildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
2082 if (wildcard != NULL) {
2083 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
2084 ((xmlSchemaAttributeGroupPtr) type)->attributeWildcard = wildcard;
2085 else
2086 type->attributeWildcard = wildcard;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002087 }
2088 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002089 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002090 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002091}
2092
2093/**
2094 * xmlSchemaParseAnnotation:
2095 * @ctxt: a schema validation context
2096 * @schema: the schema being built
2097 * @node: a subtree containing XML Schema informations
2098 *
2099 * parse a XML schema Attrribute declaration
2100 * *WARNING* this interface is highly subject to change
2101 *
William M. Bracke7091952004-05-11 15:09:58 +00002102 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002103 * 1 in case of success.
2104 */
2105static xmlSchemaAnnotPtr
2106xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2107 xmlNodePtr node)
2108{
2109 xmlSchemaAnnotPtr ret;
2110
2111 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2112 return (NULL);
2113 ret = xmlSchemaNewAnnot(ctxt, node);
2114
2115 return (ret);
2116}
2117
2118/**
2119 * xmlSchemaParseFacet:
2120 * @ctxt: a schema validation context
2121 * @schema: the schema being built
2122 * @node: a subtree containing XML Schema informations
2123 *
2124 * parse a XML schema Facet declaration
2125 * *WARNING* this interface is highly subject to change
2126 *
2127 * Returns the new type structure or NULL in case of error
2128 */
2129static xmlSchemaFacetPtr
2130xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002131 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002132{
2133 xmlSchemaFacetPtr facet;
2134 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002135 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00002136
2137 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2138 return (NULL);
2139
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002140 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002141 if (facet == NULL) {
2142 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
2143 return (NULL);
2144 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002145 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002146 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00002147 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002148 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
2149 "Facet %s has no value\n", node->name, NULL);
2150 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00002151 return (NULL);
2152 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002153 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002154 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002155 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002156 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002157 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002158 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002159 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002160 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002161 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002162 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002163 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002164 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002165 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002166 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002167 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002168 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002169 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002170 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002171 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002172 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002173 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002174 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
2175 } else if (IS_SCHEMA(node, "minLength")) {
2176 facet->type = XML_SCHEMA_FACET_MINLENGTH;
2177 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002178 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
2179 "Unknown facet type %s\n", node->name, NULL);
2180 xmlSchemaFreeFacet(facet);
2181 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002182 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002183 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002184 facet->value = value;
2185 child = node->children;
2186
2187 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002188 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2189 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002190 }
2191 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002192 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
2193 "Facet %s has unexpected child content\n",
2194 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002195 }
2196 return (facet);
2197}
2198
2199/**
2200 * xmlSchemaParseAny:
2201 * @ctxt: a schema validation context
2202 * @schema: the schema being built
2203 * @node: a subtree containing XML Schema informations
2204 *
2205 * parse a XML schema Any declaration
2206 * *WARNING* this interface is highly subject to change
2207 *
2208 * Returns the new type structure or NULL in case of error
2209 */
2210static xmlSchemaTypePtr
2211xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2212 xmlNodePtr node)
2213{
2214 xmlSchemaTypePtr type;
2215 xmlNodePtr child = NULL;
2216 xmlChar name[30];
2217
2218 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2219 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002220 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002221 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002222 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002223 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002224 type->node = node;
2225 type->type = XML_SCHEMA_TYPE_ANY;
2226 child = node->children;
2227 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2228 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2229
2230 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002231 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2232 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002233 }
2234 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002235 xmlSchemaPErr2(ctxt, node, child,
2236 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
2237 "Sequence %s has unexpected content\n", type->name,
2238 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002239 }
2240
2241 return (type);
2242}
2243
2244/**
2245 * xmlSchemaParseNotation:
2246 * @ctxt: a schema validation context
2247 * @schema: the schema being built
2248 * @node: a subtree containing XML Schema informations
2249 *
2250 * parse a XML schema Notation declaration
2251 *
2252 * Returns the new structure or NULL in case of error
2253 */
2254static xmlSchemaNotationPtr
2255xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002256 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002257{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002258 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002259 xmlSchemaNotationPtr ret;
2260 xmlNodePtr child = NULL;
2261
2262 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2263 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002264 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002265 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002266 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
2267 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002268 return (NULL);
2269 }
2270 ret = xmlSchemaAddNotation(ctxt, schema, name);
2271 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002272 return (NULL);
2273 }
2274 child = node->children;
2275 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002276 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2277 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002278 }
2279 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002280 xmlSchemaPErr2(ctxt, node, child,
2281 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
2282 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002283 }
2284
2285 return (ret);
2286}
2287
2288/**
2289 * xmlSchemaParseAnyAttribute:
2290 * @ctxt: a schema validation context
2291 * @schema: the schema being built
2292 * @node: a subtree containing XML Schema informations
2293 *
2294 * parse a XML schema AnyAttrribute declaration
2295 * *WARNING* this interface is highly subject to change
2296 *
2297 * Returns an attribute def structure or NULL
2298 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002299static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002300xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
2301 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002302{
Daniel Veillard3646d642004-06-02 19:19:14 +00002303 const xmlChar *processContents, *nsConstraint, *end, *cur, *dictMember;
2304 xmlChar *member;
2305 xmlSchemaWildcardPtr ret;
2306 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002307 xmlNodePtr child = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002308
2309 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2310 return (NULL);
2311
Daniel Veillard3646d642004-06-02 19:19:14 +00002312 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00002313 if (ret == NULL) {
2314 return (NULL);
2315 }
William M. Bracke7091952004-05-11 15:09:58 +00002316 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002317 ret->id = xmlSchemaGetProp(ctxt, node, "id");
2318 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002319 if ((processContents == NULL)
2320 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002321 ret->processContents = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002322 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002323 ret->processContents = XML_SCHEMAS_ANYATTR_SKIP;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002324 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002325 ret->processContents = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00002326 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00002327 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002328 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
William M. Bracke7091952004-05-11 15:09:58 +00002329 "anyAttribute has unexpected content "
2330 "for processContents: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002331 processContents, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00002332 ret->processContents = XML_SCHEMAS_ANYATTR_STRICT;
2333 }
2334 /*
2335 * Build the namespace constraints.
2336 */
2337 nsConstraint = xmlSchemaGetProp(ctxt, node, "namespace");
William M. Brack803812b2004-06-03 02:11:24 +00002338 if ((nsConstraint == NULL) || (xmlStrEqual(nsConstraint, BAD_CAST "##any")))
Daniel Veillard3646d642004-06-02 19:19:14 +00002339 ret->any = 1;
William M. Brack803812b2004-06-03 02:11:24 +00002340 else if (xmlStrEqual(nsConstraint, BAD_CAST "##other")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002341 ret->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
2342 if (ret->negNsSet == NULL) {
2343 xmlSchemaFreeWildcard(ret);
2344 return (NULL);
2345 }
2346 ret->negNsSet->value = schema->targetNamespace;
2347 } else {
2348 cur = nsConstraint;
2349 do {
2350 while (IS_BLANK_CH(*cur))
2351 cur++;
2352 end = cur;
2353 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
2354 end++;
2355 if (end == cur)
2356 break;
2357 member = xmlStrndup(cur, end - cur);
William M. Brack803812b2004-06-03 02:11:24 +00002358 if ((xmlStrEqual(member, BAD_CAST "##other")) ||
2359 (xmlStrEqual(member, BAD_CAST "##any"))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002360 xmlSchemaPErr(ctxt, ret->node, XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
2361 "The namespace constraint of an anyAttribute "
2362 "is a set and must not contain \"%s\"\n",
2363 member, NULL);
2364 } else {
2365 /*
2366 * TODO: Validate the value (anyURI).
2367 */
William M. Brack803812b2004-06-03 02:11:24 +00002368 if (xmlStrEqual(member, BAD_CAST "##targetNamespace")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002369 dictMember = schema->targetNamespace;
William M. Brack803812b2004-06-03 02:11:24 +00002370 } else if (xmlStrEqual(member, BAD_CAST "##local")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002371 dictMember = NULL;
2372 } else
2373 dictMember = xmlDictLookup(ctxt->dict, member, -1);
2374 /*
2375 * Avoid dublicate namespaces.
2376 */
2377 tmp = ret->nsSet;
2378 while (tmp != NULL) {
2379 if (dictMember == tmp->value)
2380 break;
2381 tmp = tmp->next;
2382 }
2383 if (tmp == NULL) {
2384 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
2385 if (tmp == NULL) {
2386 xmlFree(member);
2387 xmlSchemaFreeWildcard(ret);
2388 return (NULL);
2389 }
2390 tmp->value = dictMember;
2391 tmp->next = NULL;
2392 if (ret->nsSet == NULL)
2393 ret->nsSet = tmp;
2394 else
2395 lastNs->next = tmp;
2396 lastNs = tmp;
2397 }
2398
2399 }
2400 xmlFree(member);
2401 cur = end;
2402 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00002403 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002404
2405 child = node->children;
2406 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002407 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2408 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002409 }
2410 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002411 xmlSchemaPErr2(ctxt, node, child,
2412 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
Daniel Veillard3646d642004-06-02 19:19:14 +00002413 "anyAttribute has unexpected content\n",
2414 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002415 }
2416
2417 return (ret);
2418}
2419
2420
2421/**
2422 * xmlSchemaParseAttribute:
2423 * @ctxt: a schema validation context
2424 * @schema: the schema being built
2425 * @node: a subtree containing XML Schema informations
2426 *
2427 * parse a XML schema Attrribute declaration
2428 * *WARNING* this interface is highly subject to change
2429 *
William M. Bracke7091952004-05-11 15:09:58 +00002430 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002431 */
2432static xmlSchemaAttributePtr
2433xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002434 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002435{
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002436 const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal;
Daniel Veillard4255d502002-04-16 15:50:10 +00002437 xmlSchemaAttributePtr ret;
2438 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002439 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002440 int hasRefType = 0;
William M. Bracke7091952004-05-11 15:09:58 +00002441
2442 /*
2443 * Note that the w3c spec assumes the schema to be validated with schema
2444 * for schemas beforehand.
2445 *
2446 * 3.2.3 Constraints on XML Representations of Attribute Declarations
2447 *
2448 * TODO: Complete implementation of:
2449 * 3.2.6 Schema Component Constraint: Attribute Declaration Properties
2450 * Correct
2451 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002452
2453 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2454 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002455
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002456 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002457 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002458 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002459 /* 3.2.3 : 3.1
2460 * One of ref or name must be present, but not both
2461 */
2462 if (ref == NULL) {
2463 xmlSchemaPErr(ctxt, node,
2464 XML_SCHEMAP_ATTR_NONAME_NOREF,
2465 "Attribute declaration has no \"name\" or \"ref\"\n",
2466 NULL, NULL);
2467 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002468 }
William M. Bracke7091952004-05-11 15:09:58 +00002469 hasRefType = 1;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002470 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2471 name = (const xmlChar *) buf;
2472 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002473 if (!topLevel) {
2474 /* 3.2.3 : 3.2
2475 * If ref is present, then all of <simpleType>,
2476 * form and type must be absent.
2477 */
2478 if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2479 xmlSchemaPErr(ctxt, node,
2480 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2481 "Attribute declaration %s has \"ref\", thus "
2482 "\"form\" must be absent\n", name, NULL);
2483 }
2484 if (xmlSchemaGetProp(ctxt, node, "type") != NULL) {
2485 xmlSchemaPErr(ctxt, node,
2486 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2487 "Attribute declaration %s has \"ref\", thus "
2488 "\"type\" must be absent\n", name, NULL);
2489 }
2490 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002491 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002492 const xmlChar *ns = NULL;
2493 /* 3.2.3 : 3.1
2494 * One of ref or name must be present, but not both
2495 */
2496 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2497 xmlSchemaPErr(ctxt, node,
2498 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
Daniel Veillard3646d642004-06-02 19:19:14 +00002499 "Attribute declaration \"%s\" has both, \"name\" and "
2500 "\"ref\"\n", name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002501 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002502
William M. Bracke7091952004-05-11 15:09:58 +00002503 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2504 /* Evaluate the target namespace */
2505 if (schema->targetNamespace != NULL) {
2506 if (topLevel) {
2507 ns = schema->targetNamespace;
2508 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2509 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2510 BAD_CAST "qualified")) {
2511 ns = schema->targetNamespace;
2512 }
2513 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2514 ns = schema->targetNamespace;
2515 }
2516 }
2517 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns);
Daniel Veillard3646d642004-06-02 19:19:14 +00002518 if (ret == NULL)
2519 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002520 /* 3.2.6 Schema Component Constraint: xmlns Not Allowed */
2521 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2522 xmlSchemaPErr(ctxt, node,
2523 XML_SCHEMAP_INVALID_ATTR_NAME,
2524 "The name of an attribute declaration must not match "
2525 "\"xmlns\".\n", NULL, NULL);
2526 }
2527
2528 /* 3.2.6 Schema Component Constraint: xsi: Not Allowed */
2529 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
2530 xmlSchemaPErr(ctxt, node,
2531 XML_SCHEMAP_INVALID_ATTR_NAME,
2532 "The target namespace of an attribute declaration, "
2533 "must not match \"http://www.w3.org/2001/"
2534 "XMLSchema-instance\"", NULL, NULL);
2535 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002536 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002537 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002538 return (NULL);
2539 }
William M. Bracke7091952004-05-11 15:09:58 +00002540 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Daniel Veillard3646d642004-06-02 19:19:14 +00002541 if (topLevel)
2542 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
William M. Bracke7091952004-05-11 15:09:58 +00002543
2544 /* Handle the "use" attribute. */
2545 attrVal = xmlSchemaGetProp(ctxt, node, "use");
2546 if (attrVal != NULL) {
2547 if (xmlStrEqual(attrVal, BAD_CAST "optional"))
2548 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2549 else if (xmlStrEqual(attrVal, BAD_CAST "prohibited"))
2550 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
2551 else if (xmlStrEqual(attrVal, BAD_CAST "required"))
2552 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
2553 else
2554 xmlSchemaPErr(ctxt, node,
2555 XML_SCHEMAP_INVALID_ATTR_USE,
2556 "Attribute declaration %s has an invalid "
2557 "value for \"use\"\n", name, NULL);
2558 } else
2559 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002560
William M. Bracke7091952004-05-11 15:09:58 +00002561
2562 if (xmlSchemaGetProp(ctxt, node, "default") != NULL) {
2563 /* 3.2.3 : 1
2564 * default and fixed must not both be present.
2565 */
2566 if (xmlSchemaGetProp(ctxt, node, "fixed") != NULL) {
2567 xmlSchemaPErr(ctxt, node,
2568 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2569 "Attribute declaration has both, \"default\" "
2570 "and \"fixed\"\n", NULL, NULL);
2571 }
2572 /* 3.2.3 : 2
2573 * If default and use are both present, use must have
2574 * the actual value optional.
2575 */
2576 if (ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) {
2577 xmlSchemaPErr(ctxt, node,
2578 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2579 "Attribute declaration has \"default\" but "
2580 "\"use\" is not \"optional\"\n", NULL, NULL);
2581 }
2582 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002583
Daniel Veillard4255d502002-04-16 15:50:10 +00002584 ret->ref = ref;
2585 ret->refNs = refNs;
William M. Bracke7091952004-05-11 15:09:58 +00002586 /*
2587 * The setting of XML_SCHEMAS_ATTR_NSDEFAULT is not needed anymore,
2588 * since the target namespace was already evaluated and took
2589 * attributeFormDefault into account.
2590 */
2591 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002592 if ((ret->targetNamespace != NULL) &&
2593 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2594 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2595 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
William M. Bracke7091952004-05-11 15:09:58 +00002596 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002597 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
William M. Bracke7091952004-05-11 15:09:58 +00002598 if (ret->typeName != NULL)
2599 hasRefType = 1;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002600 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002601 child = node->children;
2602 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002603 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2604 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002605 }
2606 if (IS_SCHEMA(child, "simpleType")) {
William M. Bracke7091952004-05-11 15:09:58 +00002607 if (hasRefType) {
2608 /* 3.2.3 : 4
2609 * type and <simpleType> must not both be present.
2610 *
2611 * TODO: XML_SCHEMAP_INVALID_ATTR_COMBINATION seems not to be
2612 * a proper error type here.
2613 */
2614 xmlSchemaPErr2(ctxt, node, child,
2615 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2616 "Attribute declaration %s has both (\"ref\" or "
2617 "\"type\") and <simpleType>\n", name, NULL);
2618 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00002619 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002620 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002621 }
2622 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002623 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2624 "attribute %s has unexpected content\n", name,
2625 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002626 }
2627
2628 return (ret);
2629}
2630
2631/**
2632 * xmlSchemaParseAttributeGroup:
2633 * @ctxt: a schema validation context
2634 * @schema: the schema being built
2635 * @node: a subtree containing XML Schema informations
2636 *
2637 * parse a XML schema Attribute Group declaration
2638 * *WARNING* this interface is highly subject to change
2639 *
2640 * Returns the attribute group or NULL in case of error.
2641 */
2642static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002643xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00002644 xmlSchemaPtr schema, xmlNodePtr node,
2645 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002646{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002647 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002648 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00002649 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002650 const xmlChar *oldcontainer;
2651 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002652
2653 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2654 return (NULL);
2655 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002656 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002657 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002658 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2659 if (ref == NULL) {
2660 xmlSchemaPErr2(ctxt, node, child,
2661 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2662 "AttributeGroup has no name nor ref\n", NULL,
2663 NULL);
2664 return (NULL);
2665 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002666 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2667 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002668 if (name == NULL) {
2669 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2670 return (NULL);
2671 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002672 }
2673 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2674 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002675 return (NULL);
2676 }
2677 ret->ref = ref;
2678 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002679 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00002680 if (topLevel)
2681 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002682 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002683 child = node->children;
2684 ctxt->container = name;
2685 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002686 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2687 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002688 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002689 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
2690 /* Seems that this can be removed. */
2691 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00002692 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002693 (IS_SCHEMA(child, "attributeGroup"))) {
2694 attr = NULL;
2695 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00002696 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002697 } else if (IS_SCHEMA(child, "attributeGroup")) {
2698 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00002699 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002700 }
2701 if (attr != NULL) {
2702 if (last == NULL) {
2703 ret->attributes = attr;
2704 last = attr;
2705 } else {
2706 last->next = attr;
2707 last = attr;
2708 }
2709 }
2710 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002711 }
2712 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002713 TODO
2714 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002715 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002716 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002717 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002718 xmlSchemaPErr2(ctxt, node, child,
2719 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2720 "attribute group %s has unexpected content\n", name,
2721 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002722 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002723 ctxt->container = oldcontainer;
2724 return (ret);
2725}
2726
2727/**
2728 * xmlSchemaParseElement:
2729 * @ctxt: a schema validation context
2730 * @schema: the schema being built
2731 * @node: a subtree containing XML Schema informations
2732 *
2733 * parse a XML schema Element declaration
2734 * *WARNING* this interface is highly subject to change
2735 *
William M. Bracke7091952004-05-11 15:09:58 +00002736 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002737 */
2738static xmlSchemaElementPtr
2739xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00002740 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002741{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002742 const xmlChar *name, *fixed;
2743 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002744 xmlSchemaElementPtr ret;
2745 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002746 const xmlChar *oldcontainer;
2747 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002748 xmlAttrPtr attr;
2749
2750 /* 3.3.3 Constraints on XML Representations of Element Declarations */
2751 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002752
2753 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2754 return (NULL);
2755 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002756 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002757 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002758 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002759 /* 3.3.3 : 2.1
2760 * One of ref or name must be present, but not both
2761 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002762 if (ref == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00002763 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002764 XML_SCHEMAP_ELEM_NONAME_NOREF,
Daniel Veillard3646d642004-06-02 19:19:14 +00002765 "Element declaration has no name nor ref\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002766 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002767 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002768
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002769 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2770 name = (const xmlChar *) buf;
2771 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2772 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002773 const xmlChar *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002774
William M. Bracke7091952004-05-11 15:09:58 +00002775 /* Evaluate the target namespace */
2776 if (schema->targetNamespace != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002777 if (topLevel) {
William M. Bracke7091952004-05-11 15:09:58 +00002778 ns = schema->targetNamespace;
2779 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2780 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2781 BAD_CAST "qualified")) {
2782 ns = schema->targetNamespace;
2783 }
2784 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2785 ns = schema->targetNamespace;
2786 }
2787 }
2788 /*local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2789 ret = xmlSchemaAddElement(ctxt, schema, name, ns);
2790 /* 3.3.3 : 2.1
2791 * One of ref or name must be present, but not both
2792 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002793 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00002794 xmlSchemaPErr(ctxt, node,
2795 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2796 "Element declaration has both, \"name\" and "
2797 "\"ref\"\n", NULL, NULL);
2798 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002799 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002800 if (ret != NULL)
2801 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002802 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002803 return (NULL);
2804 }
2805 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2806 ret->ref = ref;
2807 ret->refNs = refNs;
2808 if (ref != NULL)
2809 ret->flags |= XML_SCHEMAS_ELEM_REF;
William M. Bracke7091952004-05-11 15:09:58 +00002810
2811 /* 3.3.3 : 2.2 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002812 if ((!topLevel) && (ref != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00002813 attr = node->properties;
2814 while (attr != NULL) {
2815 if ((attr->ns == NULL) &&
2816 (!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
2817 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
2818 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
2819 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
2820
2821 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2822 "Element declaration %s: only minOccurs, maxOccurs "
2823 "and id are allowed in addition to ref\n",
2824 ret->name, NULL);
2825 }
2826 attr = attr->next;
2827 }
2828 }
2829
Daniel Veillard3646d642004-06-02 19:19:14 +00002830 if (topLevel) {
2831 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002832 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Daniel Veillard3646d642004-06-02 19:19:14 +00002833 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002834 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2835 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2836 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Daniel Veillard3646d642004-06-02 19:19:14 +00002837 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillard4255d502002-04-16 15:50:10 +00002838 ctxt->container = name;
2839
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002840 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002841 ret->namedType =
William M. Bracke7091952004-05-11 15:09:58 +00002842 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002843 ret->substGroup =
2844 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2845 &(ret->substGroupNs));
Daniel Veillard3646d642004-06-02 19:19:14 +00002846 if ((ret->substGroup != NULL) && (!topLevel)) {
William M. Bracke7091952004-05-11 15:09:58 +00002847 /* 3.3.6 : 3 */
2848 /*
2849 * TODO: This seems to be redundant, since the schema for schemas
2850 * already prohibits the use of the "substitutionGroup" attribute
2851 * in local element declarations.
2852 */
2853 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2854 "Element declaration %s: substitutionGroup is allowed "
2855 "on top-level declarations only\n", ret->name, NULL);
2856
2857 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002858 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002859 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2860 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002861
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002862 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002863 if ((ret->value != NULL) && (fixed != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00002864 /* 3.3.3 : 1
2865 * default and fixed must not both be present.
2866 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002867 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2868 "Element %s has both default and fixed\n",
2869 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002870 } else if (fixed != NULL) {
2871 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002872 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002873 }
2874
2875 child = node->children;
2876 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002877 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2878 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002879 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002880
William M. Bracke7091952004-05-11 15:09:58 +00002881 if (ref != NULL) {
2882 /* 3.3.3 (2.2) */
2883 while (child != NULL) {
2884 if ((IS_SCHEMA(child, "complexType")) ||
2885 (IS_SCHEMA(child, "simpleType")) ||
2886 (IS_SCHEMA(child, "unique")) ||
2887 (IS_SCHEMA(child, "key")) ||
2888 (IS_SCHEMA(child, "keyref"))) {
2889
2890 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_REF_AND_CONTENT,
2891 "Element declaration %s: only annotation is "
2892 "allowed as content in addition to ref\n",
2893 ret->name, NULL);
2894 } else {
2895 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2896 "element %s has unexpected content\n", name, NULL);
2897 }
2898 child = child->next;
2899 }
2900 } else {
2901 if (IS_SCHEMA(child, "complexType")) {
2902 /* 3.3.3 : 3
2903 * type and either <simpleType> or <complexType> are mutually
2904 * exclusive
2905 */
2906 if (ret->namedType != NULL) {
2907 xmlSchemaPErr2(ctxt, node, child,
2908 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2909 "Element declaration %s has both \"type\" "
2910 "and a local complex type\n",
2911 ret->name, NULL);
2912 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00002913 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00002914 child = child->next;
2915 } else if (IS_SCHEMA(child, "simpleType")) {
2916 /* 3.3.3 : 3
2917 * type and either <simpleType> or <complexType> are
2918 * mutually exclusive
2919 */
2920 if (ret->namedType != NULL) {
2921 xmlSchemaPErr2(ctxt, node, child,
2922 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
2923 "Element declaration %s has both \"type\" "
2924 "and a local simple type\n",
2925 ret->name, NULL);
2926 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00002927 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00002928 child = child->next;
2929 }
2930
2931 while ((IS_SCHEMA(child, "unique")) ||
2932 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2933 TODO child = child->next;
2934 }
2935 if (child != NULL) {
2936 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2937 "element %s has unexpected content\n", name, NULL);
2938 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002939 }
2940
2941 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002942 return (ret);
2943}
2944
2945/**
2946 * xmlSchemaParseUnion:
2947 * @ctxt: a schema validation context
2948 * @schema: the schema being built
2949 * @node: a subtree containing XML Schema informations
2950 *
2951 * parse a XML schema Union definition
2952 * *WARNING* this interface is highly subject to change
2953 *
William M. Bracke7091952004-05-11 15:09:58 +00002954 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002955 * 1 in case of success.
2956 */
2957static xmlSchemaTypePtr
2958xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002959 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002960{
2961 xmlSchemaTypePtr type, subtype, last = NULL;
2962 xmlNodePtr child = NULL;
2963 xmlChar name[30];
2964
2965 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2966 return (NULL);
2967
2968
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002969 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002970 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002971 if (type == NULL)
2972 return (NULL);
2973 type->node = node;
Daniel Veillard377e1a92004-04-16 16:30:05 +00002974 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002975 type->id = xmlSchemaGetProp(ctxt, node, "id");
2976 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002977
2978 child = node->children;
2979 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002980 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2981 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002982 }
2983 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002984 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00002985 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002986 if (subtype != NULL) {
2987 if (last == NULL) {
2988 type->subtypes = subtype;
2989 last = subtype;
2990 } else {
2991 last->next = subtype;
2992 last = subtype;
2993 }
2994 last->next = NULL;
2995 }
2996 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002997 }
2998 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002999 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
3000 "Union %s has unexpected content\n", type->name,
3001 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003002 }
3003 return (type);
3004}
3005
3006/**
3007 * xmlSchemaParseList:
3008 * @ctxt: a schema validation context
3009 * @schema: the schema being built
3010 * @node: a subtree containing XML Schema informations
3011 *
3012 * parse a XML schema List definition
3013 * *WARNING* this interface is highly subject to change
3014 *
William M. Bracke7091952004-05-11 15:09:58 +00003015 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003016 * 1 in case of success.
3017 */
3018static xmlSchemaTypePtr
3019xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003020 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003021{
3022 xmlSchemaTypePtr type, subtype;
3023 xmlNodePtr child = NULL;
3024 xmlChar name[30];
3025
3026 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3027 return (NULL);
3028
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003029 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003030 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003031 if (type == NULL)
3032 return (NULL);
3033 type->node = node;
3034 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003035 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003036 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
3037
3038 child = node->children;
3039 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003040 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3041 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003042 }
William M. Bracke7091952004-05-11 15:09:58 +00003043
Daniel Veillard4255d502002-04-16 15:50:10 +00003044 subtype = NULL;
3045 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003046 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00003047 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003048 child = child->next;
3049 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003050 }
3051 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003052 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
3053 "List %s has unexpected content\n", type->name,
3054 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003055 }
3056 return (type);
3057}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003058
Daniel Veillard4255d502002-04-16 15:50:10 +00003059/**
3060 * xmlSchemaParseSimpleType:
3061 * @ctxt: a schema validation context
3062 * @schema: the schema being built
3063 * @node: a subtree containing XML Schema informations
3064 *
3065 * parse a XML schema Simple Type definition
3066 * *WARNING* this interface is highly subject to change
3067 *
William M. Bracke7091952004-05-11 15:09:58 +00003068 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003069 * 1 in case of success.
3070 */
3071static xmlSchemaTypePtr
3072xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003073 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003074{
3075 xmlSchemaTypePtr type, subtype;
3076 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003077 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00003078
3079 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3080 return (NULL);
3081
3082
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003083 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003084 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003085 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003086
William M. Bracke7091952004-05-11 15:09:58 +00003087 snprintf(buf, 99, "simpleType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003088 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00003089 } else {
3090 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
3091 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003092 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003093 if (type == NULL)
3094 return (NULL);
3095 type->node = node;
3096 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillard3646d642004-06-02 19:19:14 +00003097 if (topLevel)
3098 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003099 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003100
3101 child = node->children;
3102 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003103 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3104 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003105 }
3106 subtype = NULL;
3107 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003108 subtype = (xmlSchemaTypePtr)
3109 xmlSchemaParseRestriction(ctxt, schema, child, 1);
3110 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003111 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003112 subtype = (xmlSchemaTypePtr)
3113 xmlSchemaParseList(ctxt, schema, child);
3114 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003115 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003116 subtype = (xmlSchemaTypePtr)
3117 xmlSchemaParseUnion(ctxt, schema, child);
3118 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003119 }
3120 type->subtypes = subtype;
William M. Bracke7091952004-05-11 15:09:58 +00003121 if (subtype == NULL) {
3122 xmlSchemaPErr2(ctxt, node, child,
3123 XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD,
3124 "SimpleType %s does not define a variety\n",
3125 type->name, NULL);
3126 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003127 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003128 xmlSchemaPErr2(ctxt, node, child,
3129 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
3130 "SimpleType %s has unexpected content\n",
3131 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003132 }
3133
3134 return (type);
3135}
3136
3137
3138/**
3139 * xmlSchemaParseGroup:
3140 * @ctxt: a schema validation context
3141 * @schema: the schema being built
3142 * @node: a subtree containing XML Schema informations
3143 *
3144 * parse a XML schema Group definition
3145 * *WARNING* this interface is highly subject to change
3146 *
William M. Bracke7091952004-05-11 15:09:58 +00003147 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003148 * 1 in case of success.
3149 */
3150static xmlSchemaTypePtr
3151xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003152 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003153{
3154 xmlSchemaTypePtr type, subtype;
3155 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003156 const xmlChar *name;
3157 const xmlChar *ref = NULL, *refNs = NULL;
3158 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003159
3160 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3161 return (NULL);
3162
3163
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003164 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003165 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003166 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
3167 if (ref == NULL) {
3168 xmlSchemaPErr2(ctxt, node, child,
3169 XML_SCHEMAP_GROUP_NONAME_NOREF,
3170 "Group has no name nor ref\n", NULL, NULL);
3171 return (NULL);
3172 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003173 if (refNs == NULL)
3174 refNs = schema->targetNamespace;
3175 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
3176 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00003177 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003178 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003179 if (type == NULL)
3180 return (NULL);
3181 type->node = node;
3182 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00003183 if (topLevel)
3184 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003185 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003186 type->ref = ref;
3187 type->refNs = refNs;
3188 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3189 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3190
3191 child = node->children;
3192 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003193 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3194 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003195 }
3196 subtype = NULL;
3197 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003198 subtype = (xmlSchemaTypePtr)
3199 xmlSchemaParseAll(ctxt, schema, child);
3200 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003201 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003202 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3203 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003204 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003205 subtype = (xmlSchemaTypePtr)
3206 xmlSchemaParseSequence(ctxt, schema, child);
3207 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003208 }
3209 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003210 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003211 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003212 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
3213 "Group %s has unexpected content\n", type->name,
3214 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003215 }
3216
3217 return (type);
3218}
3219
3220/**
3221 * xmlSchemaParseAll:
3222 * @ctxt: a schema validation context
3223 * @schema: the schema being built
3224 * @node: a subtree containing XML Schema informations
3225 *
3226 * parse a XML schema All definition
3227 * *WARNING* this interface is highly subject to change
3228 *
William M. Bracke7091952004-05-11 15:09:58 +00003229 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003230 * 1 in case of success.
3231 */
3232static xmlSchemaTypePtr
3233xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003234 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003235{
3236 xmlSchemaTypePtr type, subtype, last = NULL;
3237 xmlNodePtr child = NULL;
3238 xmlChar name[30];
3239
3240 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3241 return (NULL);
3242
3243
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003244 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003245 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003246 if (type == NULL)
3247 return (NULL);
3248 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00003249 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003250 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003251 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00003252 if (type->minOccurs > 1)
3253 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
3254 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003255 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00003256 if (type->maxOccurs > 1)
3257 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
3258 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003259
3260 child = node->children;
3261 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003262 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3263 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003264 }
3265 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003266 subtype = (xmlSchemaTypePtr)
3267 xmlSchemaParseElement(ctxt, schema, child, 0);
3268 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00003269 if (subtype->minOccurs > 1)
3270 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
3271 "invalid value for minOccurs (must be 0 or 1)\n",
3272 NULL, NULL);
3273 if (subtype->maxOccurs > 1)
3274 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
3275 "invalid value for maxOccurs (must be 0 or 1)\n",
3276 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003277 if (last == NULL) {
3278 type->subtypes = subtype;
3279 last = subtype;
3280 } else {
3281 last->next = subtype;
3282 last = subtype;
3283 }
3284 last->next = NULL;
3285 }
3286 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003287 }
3288 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003289 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
3290 "All %s has unexpected content\n", type->name,
3291 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003292 }
3293
3294 return (type);
3295}
3296
3297/**
Daniel Veillard1d913862003-11-21 00:28:39 +00003298 * xmlSchemaImportSchema
3299 *
3300 * @ctxt: a schema validation context
3301 * @schemaLocation: an URI defining where to find the imported schema
3302 *
3303 * import a XML schema
3304 * *WARNING* this interface is highly subject to change
3305 *
3306 * Returns -1 in case of error and 1 in case of success.
3307 */
3308static xmlSchemaImportPtr
3309xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
3310 const xmlChar *schemaLocation)
3311{
3312 xmlSchemaImportPtr import;
3313 xmlSchemaParserCtxtPtr newctxt;
3314
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003315 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00003316 if (newctxt == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003317 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00003318 NULL);
3319 return (NULL);
3320 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003321 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
3322 /* Keep the same dictionnary for parsing, really */
3323 xmlDictReference(ctxt->dict);
3324 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003325 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003326 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
3327
Daniel Veillard1d913862003-11-21 00:28:39 +00003328 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
3329 ctxt->userData);
3330
3331 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
3332 if (import == NULL) {
3333 xmlSchemaPErrMemory(NULL, "allocating imported schema",
3334 NULL);
3335 xmlSchemaFreeParserCtxt(newctxt);
3336 return (NULL);
3337 }
3338
3339 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003340 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00003341 import->schema = xmlSchemaParse(newctxt);
3342
3343 if (import->schema == NULL) {
3344 /* FIXME use another error enum here ? */
3345 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
3346 "failed to import schema at location %s\n",
3347 schemaLocation, NULL);
3348
3349 xmlSchemaFreeParserCtxt(newctxt);
3350 if (import->schemaLocation != NULL)
3351 xmlFree((xmlChar *)import->schemaLocation);
3352 xmlFree(import);
3353 return NULL;
3354 }
3355
3356 xmlSchemaFreeParserCtxt(newctxt);
3357 return import;
3358}
3359
3360
3361/**
Daniel Veillard5a872412002-05-22 06:40:27 +00003362 * xmlSchemaParseImport:
3363 * @ctxt: a schema validation context
3364 * @schema: the schema being built
3365 * @node: a subtree containing XML Schema informations
3366 *
3367 * parse a XML schema Import definition
3368 * *WARNING* this interface is highly subject to change
3369 *
William M. Bracke7091952004-05-11 15:09:58 +00003370 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard5a872412002-05-22 06:40:27 +00003371 * 1 in case of success.
3372 */
3373static int
3374xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003375 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00003376{
3377 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00003378 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003379 const xmlChar *namespace;
3380 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00003381 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00003382 xmlURIPtr check;
3383
Daniel Veillard1d913862003-11-21 00:28:39 +00003384
Daniel Veillard5a872412002-05-22 06:40:27 +00003385 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3386 return (-1);
3387
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003388 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00003389 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003390 check = xmlParseURI((const char *) namespace);
3391 if (check == NULL) {
3392 xmlSchemaPErr2(ctxt, node, child,
3393 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
3394 "Import namespace attribute is not an URI: %s\n",
3395 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003396 return (-1);
3397 } else {
3398 xmlFreeURI(check);
3399 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003400 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003401 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00003402 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003403 xmlChar *base = NULL;
3404 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003405 check = xmlParseURI((const char *) schemaLocation);
3406 if (check == NULL) {
3407 xmlSchemaPErr2(ctxt, node, child,
3408 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
3409 "Import schemaLocation attribute is not an URI: %s\n",
3410 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003411 return (-1);
3412 } else {
3413 xmlFreeURI(check);
3414 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003415 base = xmlNodeGetBase(node->doc, node);
3416 if (base == NULL) {
3417 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3418 } else {
3419 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003420 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00003421 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003422 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003423 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3424 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00003425 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003426 }
3427 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003428 schema->schemasImports = xmlHashCreate(10);
3429 if (schema->schemasImports == NULL) {
3430 xmlSchemaPErr2(ctxt, node, child,
3431 XML_SCHEMAP_FAILED_BUILD_IMPORT,
3432 "Internal: failed to build import table\n",
3433 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003434 return (-1);
3435 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003436 }
3437 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003438 import = xmlHashLookup(schema->schemasImports,
3439 XML_SCHEMAS_DEFAULT_NAMESPACE);
3440 if (import != NULL)
3441 previous = import->schemaLocation;
3442 else
3443 previous = NULL;
3444
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003445 if (schemaLocation != NULL) {
3446 if (previous != NULL) {
3447 if (!xmlStrEqual(schemaLocation, previous)) {
3448 xmlSchemaPErr2(ctxt, node, child,
3449 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003450 "Redefining import for default namespace "
3451 "with a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003452 schemaLocation, NULL);
3453 }
3454 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003455 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3456 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003457 return (-1);
3458 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003459 xmlHashAddEntry(schema->schemasImports,
3460 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00003461 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003462 }
3463 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003464 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003465 import = xmlHashLookup(schema->schemasImports, namespace);
3466 if (import != NULL)
3467 previous = import->schemaLocation;
3468 else
3469 previous = NULL;
3470
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003471 if (schemaLocation != NULL) {
3472 if (previous != NULL) {
3473 if (!xmlStrEqual(schemaLocation, previous)) {
3474 xmlSchemaPErr2(ctxt, node, child,
3475 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003476 "Redefining import for namespace %s with "
3477 "a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003478 namespace, schemaLocation);
3479 }
3480 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003481 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3482 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003483 return (-1);
3484 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003485 if (!xmlStrEqual(import->schema->targetNamespace, namespace)) {
3486 if (namespace == NULL) {
3487 if (import->schema->targetNamespace != NULL) {
William M. Brack767265d2004-06-03 10:50:29 +00003488 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_2,
Daniel Veillard3646d642004-06-02 19:19:14 +00003489 "There is no namespace attribute on the <import> "
3490 "element information item, so the imported document "
3491 "must have no targetNamespace attribute.\n",
3492 NULL, NULL);
3493 }
3494 } else {
3495 if (import->schema->targetNamespace != NULL) {
William M. Brack767265d2004-06-03 10:50:29 +00003496 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_1,
Daniel Veillard3646d642004-06-02 19:19:14 +00003497 "The namespace attribute \"%s\" of an <import> "
3498 "element information item must be identical to the "
3499 "targetNamespace attribute \"%s\" of the "
3500 "imported document.\n",
3501 namespace, import->schema->targetNamespace);
3502 } else {
William M. Brack767265d2004-06-03 10:50:29 +00003503 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_1,
Daniel Veillard3646d642004-06-02 19:19:14 +00003504 "The namespace attribute on the <import> "
3505 "element information item, requires the imported "
3506 "document to have a targetNamespace attribute "
3507 "with the value \"%s\".\n",
3508 namespace, NULL);
3509 }
3510 }
3511 xmlSchemaFreeImport(import);
3512 return (-1);
3513 }
3514
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003515 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00003516 namespace, import);
Daniel Veillard3646d642004-06-02 19:19:14 +00003517
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003518 }
3519 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003520 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003521
3522 child = node->children;
3523 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003524 /*
3525 * the annotations here are simply discarded ...
3526 */
3527 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00003528 }
3529 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003530 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
3531 "Import has unexpected content\n", NULL, NULL);
3532 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003533 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003534 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003535}
3536
3537/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003538 * xmlSchemaCleanupDoc:
3539 * @ctxt: a schema validation context
3540 * @node: the root of the document.
3541 *
3542 * removes unwanted nodes in a schemas document tree
3543 */
3544static void
3545xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
3546{
3547 xmlNodePtr delete, cur;
3548
3549 if ((ctxt == NULL) || (root == NULL)) return;
3550
3551 /*
3552 * Remove all the blank text nodes
3553 */
3554 delete = NULL;
3555 cur = root;
3556 while (cur != NULL) {
3557 if (delete != NULL) {
3558 xmlUnlinkNode(delete);
3559 xmlFreeNode(delete);
3560 delete = NULL;
3561 }
3562 if (cur->type == XML_TEXT_NODE) {
3563 if (IS_BLANK_NODE(cur)) {
3564 if (xmlNodeGetSpacePreserve(cur) != 1) {
3565 delete = cur;
3566 }
3567 }
3568 } else if ((cur->type != XML_ELEMENT_NODE) &&
3569 (cur->type != XML_CDATA_SECTION_NODE)) {
3570 delete = cur;
3571 goto skip_children;
3572 }
3573
3574 /*
3575 * Skip to next node
3576 */
3577 if (cur->children != NULL) {
3578 if ((cur->children->type != XML_ENTITY_DECL) &&
3579 (cur->children->type != XML_ENTITY_REF_NODE) &&
3580 (cur->children->type != XML_ENTITY_NODE)) {
3581 cur = cur->children;
3582 continue;
3583 }
3584 }
3585 skip_children:
3586 if (cur->next != NULL) {
3587 cur = cur->next;
3588 continue;
3589 }
3590
3591 do {
3592 cur = cur->parent;
3593 if (cur == NULL)
3594 break;
3595 if (cur == root) {
3596 cur = NULL;
3597 break;
3598 }
3599 if (cur->next != NULL) {
3600 cur = cur->next;
3601 break;
3602 }
3603 } while (cur != NULL);
3604 }
3605 if (delete != NULL) {
3606 xmlUnlinkNode(delete);
3607 xmlFreeNode(delete);
3608 delete = NULL;
3609 }
3610}
3611
3612/**
3613 * xmlSchemaParseSchemaTopLevel:
3614 * @ctxt: a schema validation context
3615 * @schema: the schemas
3616 * @nodes: the list of top level nodes
3617 *
3618 * Returns the internal XML Schema structure built from the resource or
3619 * NULL in case of error
3620 */
3621static void
3622xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
3623 xmlSchemaPtr schema, xmlNodePtr nodes)
3624{
3625 xmlNodePtr child;
3626 xmlSchemaAnnotPtr annot;
3627
3628 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
3629 return;
3630
3631 child = nodes;
3632 while ((IS_SCHEMA(child, "include")) ||
3633 (IS_SCHEMA(child, "import")) ||
3634 (IS_SCHEMA(child, "redefine")) ||
3635 (IS_SCHEMA(child, "annotation"))) {
3636 if (IS_SCHEMA(child, "annotation")) {
3637 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3638 if (schema->annot == NULL)
3639 schema->annot = annot;
3640 else
3641 xmlSchemaFreeAnnot(annot);
3642 } else if (IS_SCHEMA(child, "import")) {
3643 xmlSchemaParseImport(ctxt, schema, child);
3644 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003645 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003646 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003647 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003648 } else if (IS_SCHEMA(child, "redefine")) {
3649 TODO
3650 }
3651 child = child->next;
3652 }
3653 while (child != NULL) {
3654 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003655 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003656 child = child->next;
3657 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003658 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003659 child = child->next;
3660 } else if (IS_SCHEMA(child, "element")) {
3661 xmlSchemaParseElement(ctxt, schema, child, 1);
3662 child = child->next;
3663 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003664 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003665 child = child->next;
3666 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003667 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003668 child = child->next;
3669 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003670 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003671 child = child->next;
3672 } else if (IS_SCHEMA(child, "notation")) {
3673 xmlSchemaParseNotation(ctxt, schema, child);
3674 child = child->next;
3675 } else {
3676 xmlSchemaPErr2(ctxt, NULL, child,
3677 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3678 "Schemas: unexpected element %s here \n",
3679 child->name, NULL);
3680 child = child->next;
3681 }
3682 while (IS_SCHEMA(child, "annotation")) {
3683 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3684 if (schema->annot == NULL)
3685 schema->annot = annot;
3686 else
3687 xmlSchemaFreeAnnot(annot);
3688 child = child->next;
3689 }
3690 }
3691}
3692
3693/**
3694 * xmlSchemaParseInclude:
3695 * @ctxt: a schema validation context
3696 * @schema: the schema being built
3697 * @node: a subtree containing XML Schema informations
3698 *
3699 * parse a XML schema Include definition
3700 *
William M. Bracke7091952004-05-11 15:09:58 +00003701 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003702 * 1 in case of success.
3703 */
3704static int
3705xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3706 xmlNodePtr node)
3707{
3708 xmlNodePtr child = NULL;
3709 const xmlChar *schemaLocation;
3710 xmlURIPtr check;
3711 xmlDocPtr doc;
3712 xmlNodePtr root;
3713 xmlSchemaIncludePtr include;
3714
3715
3716 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3717 return (-1);
3718
3719 /*
3720 * Preliminary step, extract the URI-Reference for the include and
3721 * make an URI from the base.
3722 */
3723 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
3724 if (schemaLocation != NULL) {
3725 xmlChar *base = NULL;
3726 xmlChar *URI = NULL;
3727 check = xmlParseURI((const char *) schemaLocation);
3728 if (check == NULL) {
3729 xmlSchemaPErr2(ctxt, node, child,
3730 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3731 "Include schemaLocation attribute is not an URI: %s\n",
3732 schemaLocation, NULL);
3733 return (-1);
3734 } else {
3735 xmlFreeURI(check);
3736 }
3737 base = xmlNodeGetBase(node->doc, node);
3738 if (base == NULL) {
3739 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3740 } else {
3741 URI = xmlBuildURI(schemaLocation, base);
3742 xmlFree(base);
3743 }
3744 if (URI != NULL) {
3745 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3746 xmlFree(URI);
3747 }
3748 } else {
3749 xmlSchemaPErr2(ctxt, node, child,
3750 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3751 "Include schemaLocation attribute missing\n",
3752 NULL, NULL);
3753 return (-1);
3754 }
3755
3756 child = node->children;
3757 while (IS_SCHEMA(child, "annotation")) {
3758 /*
3759 * the annotations here are simply discarded ...
3760 */
3761 child = child->next;
3762 }
3763 if (child != NULL) {
3764 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3765 "Include has unexpected content\n", NULL, NULL);
3766 return (-1);
3767 }
3768
3769 /*
3770 * First step is to parse the input document into an DOM/Infoset
3771 */
3772 doc = xmlReadFile((const char *) schemaLocation, NULL,
3773 SCHEMAS_PARSE_OPTIONS);
3774 if (doc == NULL) {
3775 xmlSchemaPErr(ctxt, NULL,
3776 XML_SCHEMAP_FAILED_LOAD,
3777 "xmlSchemaParse: could not load %s\n",
3778 ctxt->URL, NULL);
3779 return(-1);
3780 }
3781
3782 /*
3783 * Then extract the root of the schema
3784 */
3785 root = xmlDocGetRootElement(doc);
3786 if (root == NULL) {
3787 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3788 XML_SCHEMAP_NOROOT,
3789 "schemas %s has no root", schemaLocation, NULL);
3790 xmlFreeDoc(doc);
3791 return (-1);
3792 }
3793
3794 /*
3795 * Remove all the blank text nodes
3796 */
3797 xmlSchemaCleanupDoc(ctxt, root);
3798
3799 /*
3800 * Check the schemas top level element
3801 */
3802 if (!IS_SCHEMA(root, "schema")) {
3803 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3804 XML_SCHEMAP_NOT_SCHEMA,
3805 "File %s is not a schemas", schemaLocation, NULL);
3806 xmlFreeDoc(doc);
3807 return (-1);
3808 }
3809
3810 /*
3811 * register the include
3812 */
3813 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3814 if (include == NULL) {
3815 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3816 xmlFreeDoc(doc);
3817 return (-1);
3818 }
3819
3820 memset(include, 0, sizeof(xmlSchemaInclude));
3821 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3822 include->doc = doc;
3823 include->next = schema->includes;
3824 schema->includes = include;
3825
3826
3827 /*
3828 * parse the declarations in the included file like if they
3829 * were in the original file.
3830 */
3831 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3832
3833 return (1);
3834}
3835
3836/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003837 * xmlSchemaParseChoice:
3838 * @ctxt: a schema validation context
3839 * @schema: the schema being built
3840 * @node: a subtree containing XML Schema informations
3841 *
3842 * parse a XML schema Choice definition
3843 * *WARNING* this interface is highly subject to change
3844 *
William M. Bracke7091952004-05-11 15:09:58 +00003845 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003846 * 1 in case of success.
3847 */
3848static xmlSchemaTypePtr
3849xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003850 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003851{
3852 xmlSchemaTypePtr type, subtype, last = NULL;
3853 xmlNodePtr child = NULL;
3854 xmlChar name[30];
3855
3856 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3857 return (NULL);
3858
3859
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003860 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003861 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003862 if (type == NULL)
3863 return (NULL);
3864 type->node = node;
3865 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003866 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003867 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3868 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3869
3870 child = node->children;
3871 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003872 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3873 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003874 }
3875 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003876 (IS_SCHEMA(child, "group")) ||
3877 (IS_SCHEMA(child, "any")) ||
3878 (IS_SCHEMA(child, "choice")) ||
3879 (IS_SCHEMA(child, "sequence"))) {
3880 subtype = NULL;
3881 if (IS_SCHEMA(child, "element")) {
3882 subtype = (xmlSchemaTypePtr)
3883 xmlSchemaParseElement(ctxt, schema, child, 0);
3884 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003885 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003886 } else if (IS_SCHEMA(child, "any")) {
3887 subtype = xmlSchemaParseAny(ctxt, schema, child);
3888 } else if (IS_SCHEMA(child, "sequence")) {
3889 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3890 } else if (IS_SCHEMA(child, "choice")) {
3891 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3892 }
3893 if (subtype != NULL) {
3894 if (last == NULL) {
3895 type->subtypes = subtype;
3896 last = subtype;
3897 } else {
3898 last->next = subtype;
3899 last = subtype;
3900 }
3901 last->next = NULL;
3902 }
3903 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003904 }
3905 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003906 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3907 "Choice %s has unexpected content\n", type->name,
3908 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003909 }
3910
3911 return (type);
3912}
3913
3914/**
3915 * xmlSchemaParseSequence:
3916 * @ctxt: a schema validation context
3917 * @schema: the schema being built
3918 * @node: a subtree containing XML Schema informations
3919 *
3920 * parse a XML schema Sequence definition
3921 * *WARNING* this interface is highly subject to change
3922 *
William M. Bracke7091952004-05-11 15:09:58 +00003923 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003924 * 1 in case of success.
3925 */
3926static xmlSchemaTypePtr
3927xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003928 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003929{
3930 xmlSchemaTypePtr type, subtype, last = NULL;
3931 xmlNodePtr child = NULL;
3932 xmlChar name[30];
3933
3934 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3935 return (NULL);
3936
3937
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003938 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003939 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003940 if (type == NULL)
3941 return (NULL);
3942 type->node = node;
3943 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003944 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003945 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3946 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3947
3948 child = node->children;
3949 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003950 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3951 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003952 }
3953 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003954 (IS_SCHEMA(child, "group")) ||
3955 (IS_SCHEMA(child, "any")) ||
3956 (IS_SCHEMA(child, "choice")) ||
3957 (IS_SCHEMA(child, "sequence"))) {
3958 subtype = NULL;
3959 if (IS_SCHEMA(child, "element")) {
3960 subtype = (xmlSchemaTypePtr)
3961 xmlSchemaParseElement(ctxt, schema, child, 0);
3962 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003963 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003964 } else if (IS_SCHEMA(child, "any")) {
3965 subtype = xmlSchemaParseAny(ctxt, schema, child);
3966 } else if (IS_SCHEMA(child, "choice")) {
3967 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3968 } else if (IS_SCHEMA(child, "sequence")) {
3969 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3970 }
3971 if (subtype != NULL) {
3972 if (last == NULL) {
3973 type->subtypes = subtype;
3974 last = subtype;
3975 } else {
3976 last->next = subtype;
3977 last = subtype;
3978 }
3979 last->next = NULL;
3980 }
3981 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003982 }
3983 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003984 xmlSchemaPErr2(ctxt, node, child,
3985 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3986 "Sequence %s has unexpected content\n", type->name,
3987 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003988 }
3989
3990 return (type);
3991}
3992
3993/**
3994 * xmlSchemaParseRestriction:
3995 * @ctxt: a schema validation context
3996 * @schema: the schema being built
3997 * @node: a subtree containing XML Schema informations
3998 * @simple: is that part of a simple type.
3999 *
4000 * parse a XML schema Restriction definition
4001 * *WARNING* this interface is highly subject to change
4002 *
4003 * Returns the type definition or NULL in case of error
4004 */
4005static xmlSchemaTypePtr
4006xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4007 xmlNodePtr node, int simple)
4008{
4009 xmlSchemaTypePtr type, subtype;
4010 xmlSchemaFacetPtr facet, lastfacet = NULL;
4011 xmlNodePtr child = NULL;
4012 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004013 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00004014
4015 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4016 return (NULL);
4017
4018 oldcontainer = ctxt->container;
4019
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004020 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004021 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004022 if (type == NULL)
4023 return (NULL);
4024 type->node = node;
4025 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004026 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004027 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
4028 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004029 xmlSchemaPErr2(ctxt, node, child,
4030 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
4031 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004032 }
4033 ctxt->container = name;
4034
4035 child = node->children;
4036 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004037 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4038 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004039 }
4040 subtype = NULL;
4041
4042 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004043 subtype = (xmlSchemaTypePtr)
4044 xmlSchemaParseAll(ctxt, schema, child);
4045 child = child->next;
4046 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004047 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004048 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4049 child = child->next;
4050 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004051 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004052 subtype = (xmlSchemaTypePtr)
4053 xmlSchemaParseSequence(ctxt, schema, child);
4054 child = child->next;
4055 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004056 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004057 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004058 xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004059 child = child->next;
4060 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004061 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004062 if (IS_SCHEMA(child, "simpleType")) {
4063 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004064 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004065 child = child->next;
4066 type->baseType = subtype;
4067 }
4068 /*
4069 * Facets
4070 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004071 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004072 (IS_SCHEMA(child, "minExclusive")) ||
4073 (IS_SCHEMA(child, "maxInclusive")) ||
4074 (IS_SCHEMA(child, "maxExclusive")) ||
4075 (IS_SCHEMA(child, "totalDigits")) ||
4076 (IS_SCHEMA(child, "fractionDigits")) ||
4077 (IS_SCHEMA(child, "pattern")) ||
4078 (IS_SCHEMA(child, "enumeration")) ||
4079 (IS_SCHEMA(child, "whiteSpace")) ||
4080 (IS_SCHEMA(child, "length")) ||
4081 (IS_SCHEMA(child, "maxLength")) ||
4082 (IS_SCHEMA(child, "minLength"))) {
4083 facet = xmlSchemaParseFacet(ctxt, schema, child);
4084 if (facet != NULL) {
4085 if (lastfacet == NULL) {
4086 type->facets = facet;
4087 lastfacet = facet;
4088 } else {
4089 lastfacet->next = facet;
4090 lastfacet = facet;
4091 }
4092 lastfacet->next = NULL;
4093 }
4094 child = child->next;
4095 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004096 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004097 /* TODO: a restriction of simpleType does not contain any
4098 * attribute declarations.
4099 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004100 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
4101 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004102 xmlSchemaPErr2(ctxt, node, child,
4103 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
4104 "Restriction %s has unexpected content\n",
4105 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004106 }
4107 ctxt->container = oldcontainer;
4108 return (type);
4109}
4110
4111/**
4112 * xmlSchemaParseExtension:
4113 * @ctxt: a schema validation context
4114 * @schema: the schema being built
4115 * @node: a subtree containing XML Schema informations
4116 *
4117 * parse a XML schema Extension definition
4118 * *WARNING* this interface is highly subject to change
4119 *
4120 * Returns the type definition or NULL in case of error
4121 */
4122static xmlSchemaTypePtr
4123xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004124 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004125{
4126 xmlSchemaTypePtr type, subtype;
4127 xmlNodePtr child = NULL;
4128 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004129 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00004130
4131 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4132 return (NULL);
4133
4134 oldcontainer = ctxt->container;
4135
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004136 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004137 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004138 if (type == NULL)
4139 return (NULL);
4140 type->node = node;
4141 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004142 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004143 ctxt->container = name;
4144
4145 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
4146 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004147 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
4148 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004149 }
4150 child = node->children;
4151 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004152 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4153 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004154 }
4155 subtype = NULL;
4156
4157 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004158 subtype = xmlSchemaParseAll(ctxt, schema, child);
4159 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004160 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004161 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4162 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004163 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004164 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4165 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004166 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004167 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004168 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004169 }
4170 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004171 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004172 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
4173 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004174 xmlSchemaPErr2(ctxt, node, child,
4175 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
4176 "Extension %s has unexpected content\n", type->name,
4177 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004178 }
4179 ctxt->container = oldcontainer;
4180 return (type);
4181}
4182
4183/**
4184 * xmlSchemaParseSimpleContent:
4185 * @ctxt: a schema validation context
4186 * @schema: the schema being built
4187 * @node: a subtree containing XML Schema informations
4188 *
4189 * parse a XML schema SimpleContent definition
4190 * *WARNING* this interface is highly subject to change
4191 *
4192 * Returns the type definition or NULL in case of error
4193 */
4194static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004195xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
4196 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004197{
4198 xmlSchemaTypePtr type, subtype;
4199 xmlNodePtr child = NULL;
4200 xmlChar name[30];
4201
4202 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4203 return (NULL);
4204
William M. Bracke7091952004-05-11 15:09:58 +00004205 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004206 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004207 if (type == NULL)
4208 return (NULL);
4209 type->node = node;
4210 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004211 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004212
4213 child = node->children;
4214 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004215 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4216 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004217 }
4218 subtype = NULL;
4219 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004220 subtype = (xmlSchemaTypePtr)
4221 xmlSchemaParseRestriction(ctxt, schema, child, 0);
4222 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004223 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004224 subtype = (xmlSchemaTypePtr)
4225 xmlSchemaParseExtension(ctxt, schema, child);
4226 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004227 }
4228 type->subtypes = subtype;
4229 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004230 xmlSchemaPErr2(ctxt, node, child,
4231 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
4232 "SimpleContent %s has unexpected content\n",
4233 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004234 }
4235 return (type);
4236}
4237
4238/**
4239 * xmlSchemaParseComplexContent:
4240 * @ctxt: a schema validation context
4241 * @schema: the schema being built
4242 * @node: a subtree containing XML Schema informations
4243 *
4244 * parse a XML schema ComplexContent definition
4245 * *WARNING* this interface is highly subject to change
4246 *
4247 * Returns the type definition or NULL in case of error
4248 */
4249static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004250xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
4251 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004252{
4253 xmlSchemaTypePtr type, subtype;
4254 xmlNodePtr child = NULL;
4255 xmlChar name[30];
4256
4257 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4258 return (NULL);
4259
4260
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004261 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004262 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004263 if (type == NULL)
4264 return (NULL);
4265 type->node = node;
4266 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004267 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004268
4269 child = node->children;
4270 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004271 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4272 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004273 }
4274 subtype = NULL;
4275 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004276 subtype = (xmlSchemaTypePtr)
4277 xmlSchemaParseRestriction(ctxt, schema, child, 0);
4278 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004279 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004280 subtype = (xmlSchemaTypePtr)
4281 xmlSchemaParseExtension(ctxt, schema, child);
4282 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004283 }
4284 type->subtypes = subtype;
4285 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004286 xmlSchemaPErr2(ctxt, node, child,
4287 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
4288 "ComplexContent %s has unexpected content\n",
4289 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004290 }
4291 return (type);
4292}
4293
4294/**
4295 * xmlSchemaParseComplexType:
4296 * @ctxt: a schema validation context
4297 * @schema: the schema being built
4298 * @node: a subtree containing XML Schema informations
4299 *
4300 * parse a XML schema Complex Type definition
4301 * *WARNING* this interface is highly subject to change
4302 *
4303 * Returns the type definition or NULL in case of error
4304 */
4305static xmlSchemaTypePtr
4306xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004307 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004308{
4309 xmlSchemaTypePtr type, subtype;
4310 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004311 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00004312 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004313 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00004314
4315 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4316 return (NULL);
4317
4318 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004319 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004320 if (name == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00004321 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004322 name = (const xmlChar *)buf;
4323 type = xmlSchemaAddType(ctxt, schema, name, NULL);
4324 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004325
William M. Bracke7091952004-05-11 15:09:58 +00004326 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
4327 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004328 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004329 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004330 return (NULL);
4331 }
William M. Bracke7091952004-05-11 15:09:58 +00004332 if (xmlGetBooleanProp(ctxt, node, "mixed", 0))
4333 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004334
Daniel Veillard4255d502002-04-16 15:50:10 +00004335 type->node = node;
4336 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillard3646d642004-06-02 19:19:14 +00004337 if (topLevel)
4338 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004339 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004340 ctxt->container = name;
4341
4342 child = node->children;
4343 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004344 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4345 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004346 }
4347 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00004348 /* 3.4.3 : 2.2
4349 * Specifying mixed='true' when the <simpleContent>
4350 * alternative is chosen has no effect
4351 */
4352 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
4353 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004354 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
4355 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004356 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004357 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
4358 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004359 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004360 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004361
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004362 if (IS_SCHEMA(child, "all")) {
4363 subtype = xmlSchemaParseAll(ctxt, schema, child);
4364 child = child->next;
4365 } else if (IS_SCHEMA(child, "choice")) {
4366 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4367 child = child->next;
4368 } else if (IS_SCHEMA(child, "sequence")) {
4369 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4370 child = child->next;
4371 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004372 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004373 child = child->next;
4374 }
4375 if (subtype != NULL)
4376 type->subtypes = subtype;
4377 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004378 }
4379 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004380 xmlSchemaPErr2(ctxt, node, child,
4381 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
4382 "ComplexType %s has unexpected content\n",
4383 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004384 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004385 if (type->attributeWildcard != NULL)
4386 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillard4255d502002-04-16 15:50:10 +00004387 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00004388 return (type);
4389}
4390
Daniel Veillard4255d502002-04-16 15:50:10 +00004391/**
4392 * xmlSchemaParseSchema:
4393 * @ctxt: a schema validation context
4394 * @node: a subtree containing XML Schema informations
4395 *
4396 * parse a XML schema definition from a node set
4397 * *WARNING* this interface is highly subject to change
4398 *
4399 * Returns the internal XML Schema structure built from the resource or
4400 * NULL in case of error
4401 */
4402static xmlSchemaPtr
4403xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4404{
4405 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004406 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004407 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004408 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004409
4410 if ((ctxt == NULL) || (node == NULL))
4411 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004412
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004413 nberrors = ctxt->nberrors;
4414 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004415 if (IS_SCHEMA(node, "schema")) {
4416 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004417 if (schema == NULL)
4418 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004419 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
4420 if (val != NULL) {
4421 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
4422 } else {
4423 schema->targetNamespace = NULL;
4424 }
4425 schema->id = xmlSchemaGetProp(ctxt, node, "id");
4426 schema->version = xmlSchemaGetProp(ctxt, node, "version");
4427 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004428 if (val != NULL) {
4429 if (xmlStrEqual(val, BAD_CAST "qualified"))
4430 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
4431 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4432 xmlSchemaPErr2(ctxt, node, child,
4433 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
4434 "Invalid value %s for elementFormDefault\n",
4435 val, NULL);
4436 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004437 } else {
4438 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
4439 }
4440 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004441 if (val != NULL) {
4442 if (xmlStrEqual(val, BAD_CAST "qualified"))
4443 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
4444 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4445 xmlSchemaPErr2(ctxt, node, child,
4446 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
4447 "Invalid value %s for attributeFormDefault\n",
4448 val, NULL);
4449 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004450 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004451
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004452 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
4453 } else {
4454 xmlDocPtr doc;
4455
4456 doc = node->doc;
4457
4458 if ((doc != NULL) && (doc->URL != NULL)) {
4459 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4460 XML_SCHEMAP_NOT_SCHEMA,
4461 "File %s is not a schemas", doc->URL, NULL);
4462 } else {
4463 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4464 XML_SCHEMAP_NOT_SCHEMA,
4465 "File is not a schemas", NULL, NULL);
4466 }
4467 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004468 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004469 if (ctxt->nberrors != 0) {
4470 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004471 xmlSchemaFree(schema);
4472 schema = NULL;
4473 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004474 }
4475 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004476#ifdef DEBUG
4477 if (schema == NULL)
4478 xmlGenericError(xmlGenericErrorContext,
4479 "xmlSchemaParse() failed\n");
4480#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004481 return (schema);
4482}
4483
4484/************************************************************************
4485 * *
4486 * Validating using Schemas *
4487 * *
4488 ************************************************************************/
4489
4490/************************************************************************
4491 * *
4492 * Reading/Writing Schemas *
4493 * *
4494 ************************************************************************/
4495
4496/**
4497 * xmlSchemaNewParserCtxt:
4498 * @URL: the location of the schema
4499 *
4500 * Create an XML Schemas parse context for that file/resource expected
4501 * to contain an XML Schemas file.
4502 *
4503 * Returns the parser context or NULL in case of error
4504 */
4505xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004506xmlSchemaNewParserCtxt(const char *URL)
4507{
Daniel Veillard4255d502002-04-16 15:50:10 +00004508 xmlSchemaParserCtxtPtr ret;
4509
4510 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004511 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004512
4513 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4514 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004515 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4516 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004517 return (NULL);
4518 }
4519 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004520 ret->dict = xmlDictCreate();
4521 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004522 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004523 return (ret);
4524}
4525
4526/**
Daniel Veillard6045c902002-10-09 21:13:59 +00004527 * xmlSchemaNewMemParserCtxt:
4528 * @buffer: a pointer to a char array containing the schemas
4529 * @size: the size of the array
4530 *
4531 * Create an XML Schemas parse context for that memory buffer expected
4532 * to contain an XML Schemas file.
4533 *
4534 * Returns the parser context or NULL in case of error
4535 */
4536xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004537xmlSchemaNewMemParserCtxt(const char *buffer, int size)
4538{
Daniel Veillard6045c902002-10-09 21:13:59 +00004539 xmlSchemaParserCtxtPtr ret;
4540
4541 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004542 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00004543
4544 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4545 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004546 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4547 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00004548 return (NULL);
4549 }
4550 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4551 ret->buffer = buffer;
4552 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00004553 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00004554 return (ret);
4555}
4556
4557/**
Daniel Veillard9d751502003-10-29 13:21:47 +00004558 * xmlSchemaNewDocParserCtxt:
4559 * @doc: a preparsed document tree
4560 *
4561 * Create an XML Schemas parse context for that document.
4562 * NB. The document may be modified during the parsing process.
4563 *
4564 * Returns the parser context or NULL in case of error
4565 */
4566xmlSchemaParserCtxtPtr
4567xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
4568{
4569 xmlSchemaParserCtxtPtr ret;
4570
4571 if (doc == NULL)
4572 return (NULL);
4573
4574 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4575 if (ret == NULL) {
4576 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
4577 NULL);
4578 return (NULL);
4579 }
4580 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4581 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00004582 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00004583 /* The application has responsibility for the document */
4584 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00004585
4586 return (ret);
4587}
4588
4589/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004590 * xmlSchemaFreeParserCtxt:
4591 * @ctxt: the schema parser context
4592 *
4593 * Free the resources associated to the schema parser context
4594 */
4595void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004596xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
4597{
Daniel Veillard4255d502002-04-16 15:50:10 +00004598 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004599 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004600 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004601 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004602 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004603 xmlFree(ctxt);
4604}
4605
4606/************************************************************************
4607 * *
4608 * Building the content models *
4609 * *
4610 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004611
Daniel Veillard4255d502002-04-16 15:50:10 +00004612/**
4613 * xmlSchemaBuildAContentModel:
4614 * @type: the schema type definition
4615 * @ctxt: the schema parser context
4616 * @name: the element name whose content is being built
4617 *
4618 * Generate the automata sequence needed for that type
4619 */
4620static void
4621xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004622 xmlSchemaParserCtxtPtr ctxt,
4623 const xmlChar * name)
4624{
Daniel Veillard4255d502002-04-16 15:50:10 +00004625 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004626 xmlGenericError(xmlGenericErrorContext,
4627 "Found unexpected type = NULL in %s content model\n",
4628 name);
4629 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004630 }
4631 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004632 case XML_SCHEMA_TYPE_ANY:
4633 /* TODO : handle the namespace too */
4634 /* TODO : make that a specific transition type */
4635 TODO ctxt->state =
4636 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
4637 BAD_CAST "*", NULL);
4638 break;
4639 case XML_SCHEMA_TYPE_ELEMENT:{
4640 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00004641
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004642 /* TODO : handle the namespace too */
4643 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004644
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004645 if (elem->maxOccurs >= UNBOUNDED) {
4646 if (elem->minOccurs > 1) {
4647 xmlAutomataStatePtr tmp;
4648 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00004649
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004650 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4651 oldstate,
4652 NULL);
4653 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004654
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004655 counter = xmlAutomataNewCounter(ctxt->am,
4656 elem->minOccurs -
4657 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00004658
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004659 if (elem->refDecl != NULL) {
4660 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4661 elem->refDecl,
4662 ctxt,
4663 elem->refDecl->
4664 name);
4665 } else {
4666 ctxt->state =
4667 xmlAutomataNewTransition(ctxt->am,
4668 ctxt->state, NULL,
4669 elem->name, type);
4670 }
4671 tmp = ctxt->state;
4672 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4673 counter);
4674 ctxt->state =
4675 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4676 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00004677
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004678 } else {
4679 if (elem->refDecl != NULL) {
4680 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4681 elem->refDecl,
4682 ctxt,
4683 elem->refDecl->
4684 name);
4685 } else {
4686 ctxt->state =
4687 xmlAutomataNewTransition(ctxt->am,
4688 ctxt->state, NULL,
4689 elem->name, type);
4690 }
4691 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4692 oldstate);
4693 if (elem->minOccurs == 0) {
4694 /* basically an elem* */
4695 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4696 ctxt->state);
4697 }
4698 }
4699 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
4700 xmlAutomataStatePtr tmp;
4701 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00004702
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004703 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4704 oldstate, NULL);
4705 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004706
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004707 counter = xmlAutomataNewCounter(ctxt->am,
4708 elem->minOccurs - 1,
4709 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004710
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004711 if (elem->refDecl != NULL) {
4712 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4713 elem->refDecl, ctxt,
4714 elem->refDecl->name);
4715 } else {
4716 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4717 ctxt->state,
4718 NULL,
4719 elem->name,
4720 type);
4721 }
4722 tmp = ctxt->state;
4723 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4724 counter);
4725 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
4726 NULL,
4727 counter);
4728 if (elem->minOccurs == 0) {
4729 /* basically an elem? */
4730 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4731 ctxt->state);
4732 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00004733
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004734 } else {
4735 if (elem->refDecl != NULL) {
4736 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4737 elem->refDecl, ctxt,
4738 elem->refDecl->name);
4739 } else {
4740 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4741 ctxt->state,
4742 NULL,
4743 elem->name,
4744 type);
4745 }
4746 if (elem->minOccurs == 0) {
4747 /* basically an elem? */
4748 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4749 ctxt->state);
4750 }
4751 }
4752 break;
4753 }
4754 case XML_SCHEMA_TYPE_SEQUENCE:{
4755 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004756
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004757 /*
4758 * If max and min occurances are default (1) then
4759 * simply iterate over the subtypes
4760 */
4761 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4762 subtypes = type->subtypes;
4763 while (subtypes != NULL) {
4764 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4765 subtypes = subtypes->next;
4766 }
4767 } else {
4768 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004769
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004770 if (type->maxOccurs >= UNBOUNDED) {
4771 if (type->minOccurs > 1) {
4772 xmlAutomataStatePtr tmp;
4773 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004774
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004775 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4776 oldstate,
4777 NULL);
4778 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004779
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004780 counter = xmlAutomataNewCounter(ctxt->am,
4781 type->
4782 minOccurs - 1,
4783 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004784
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004785 subtypes = type->subtypes;
4786 while (subtypes != NULL) {
4787 xmlSchemaBuildAContentModel(subtypes, ctxt,
4788 name);
4789 subtypes = subtypes->next;
4790 }
4791 tmp = ctxt->state;
4792 xmlAutomataNewCountedTrans(ctxt->am, tmp,
4793 oldstate, counter);
4794 ctxt->state =
4795 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4796 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004797
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004798 } else {
4799 subtypes = type->subtypes;
4800 while (subtypes != NULL) {
4801 xmlSchemaBuildAContentModel(subtypes, ctxt,
4802 name);
4803 subtypes = subtypes->next;
4804 }
4805 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4806 oldstate);
4807 if (type->minOccurs == 0) {
4808 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4809 ctxt->state);
4810 }
4811 }
4812 } else if ((type->maxOccurs > 1)
4813 || (type->minOccurs > 1)) {
4814 xmlAutomataStatePtr tmp;
4815 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004816
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004817 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4818 oldstate,
4819 NULL);
4820 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00004821
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004822 counter = xmlAutomataNewCounter(ctxt->am,
4823 type->minOccurs -
4824 1,
4825 type->maxOccurs -
4826 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004827
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004828 subtypes = type->subtypes;
4829 while (subtypes != NULL) {
4830 xmlSchemaBuildAContentModel(subtypes, ctxt,
4831 name);
4832 subtypes = subtypes->next;
4833 }
4834 tmp = ctxt->state;
4835 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4836 counter);
4837 ctxt->state =
4838 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4839 counter);
4840 if (type->minOccurs == 0) {
4841 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4842 ctxt->state);
4843 }
Daniel Veillardb509f152002-04-17 16:28:10 +00004844
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004845 } else {
4846 subtypes = type->subtypes;
4847 while (subtypes != NULL) {
4848 xmlSchemaBuildAContentModel(subtypes, ctxt,
4849 name);
4850 subtypes = subtypes->next;
4851 }
4852 if (type->minOccurs == 0) {
4853 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4854 ctxt->state);
4855 }
4856 }
4857 }
4858 break;
4859 }
4860 case XML_SCHEMA_TYPE_CHOICE:{
4861 xmlSchemaTypePtr subtypes;
4862 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00004863
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004864 start = ctxt->state;
4865 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00004866
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004867 /*
4868 * iterate over the subtypes and remerge the end with an
4869 * epsilon transition
4870 */
4871 if (type->maxOccurs == 1) {
4872 subtypes = type->subtypes;
4873 while (subtypes != NULL) {
4874 ctxt->state = start;
4875 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4876 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4877 subtypes = subtypes->next;
4878 }
4879 } else {
4880 int counter;
4881 xmlAutomataStatePtr hop;
4882 int maxOccurs = type->maxOccurs == UNBOUNDED ?
4883 UNBOUNDED : type->maxOccurs - 1;
4884 int minOccurs =
4885 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00004886
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004887 /*
4888 * use a counter to keep track of the number of transtions
4889 * which went through the choice.
4890 */
4891 counter =
4892 xmlAutomataNewCounter(ctxt->am, minOccurs,
4893 maxOccurs);
4894 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00004895
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004896 subtypes = type->subtypes;
4897 while (subtypes != NULL) {
4898 ctxt->state = start;
4899 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4900 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4901 subtypes = subtypes->next;
4902 }
4903 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4904 counter);
4905 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4906 counter);
4907 }
4908 if (type->minOccurs == 0) {
4909 xmlAutomataNewEpsilon(ctxt->am, start, end);
4910 }
4911 ctxt->state = end;
4912 break;
4913 }
4914 case XML_SCHEMA_TYPE_ALL:{
4915 xmlAutomataStatePtr start;
4916 xmlSchemaTypePtr subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +00004917 /*
4918 * Changed, since type in not an xmlSchemaElement here.
4919 */
4920 /* xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type; */
4921 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004922 int lax;
4923
4924 subtypes = type->subtypes;
4925 if (subtypes == NULL)
4926 break;
4927 start = ctxt->state;
4928 while (subtypes != NULL) {
4929 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00004930 /*
4931 * the following 'if' was needed to fix bug 139897
4932 * not quite sure why it only needs to be done for
4933 * elements with a 'ref', but it seems to work ok.
4934 */
4935 if (subtypes->ref != NULL)
4936 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
William M. Bracke7091952004-05-11 15:09:58 +00004937 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004938 /* TODO : handle the namespace too */
4939 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4940 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4941 ctxt->state, elem->name, 1,
4942 1, subtypes);
4943 } else {
4944 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4945 ctxt->state, elem->name,
4946 elem->minOccurs,
4947 elem->maxOccurs,
4948 subtypes);
4949 }
4950 subtypes = subtypes->next;
4951 }
4952 lax = type->minOccurs == 0;
4953 ctxt->state =
4954 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4955 lax);
4956 break;
4957 }
4958 case XML_SCHEMA_TYPE_RESTRICTION:
4959 if (type->subtypes != NULL)
4960 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4961 break;
4962 case XML_SCHEMA_TYPE_EXTENSION:
4963 if (type->baseType != NULL) {
4964 xmlSchemaTypePtr subtypes;
4965
Daniel Veillardf7627552004-04-22 07:15:40 +00004966 if (type->recurse) {
4967 xmlSchemaPErr(ctxt, type->node,
4968 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4969 "Schemas: extension type %s is recursive\n",
4970 type->name, NULL);
4971 return;
4972 }
4973 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004974 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00004975 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004976 subtypes = type->subtypes;
4977 while (subtypes != NULL) {
4978 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4979 subtypes = subtypes->next;
4980 }
4981 } else if (type->subtypes != NULL)
4982 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4983 break;
4984 case XML_SCHEMA_TYPE_GROUP:
4985 if (type->subtypes == NULL) {
William M. Brack29aa7722004-05-12 00:27:56 +00004986 xmlSchemaTypePtr rgroup;
4987 if (type->ref != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004988 rgroup = xmlSchemaGetGroup(ctxt->schema, type->ref,
William M. Brack29aa7722004-05-12 00:27:56 +00004989 type->refNs);
4990 if (rgroup == NULL) {
4991 xmlSchemaPErr(ctxt, type->node,
4992 XML_SCHEMAP_UNKNOWN_REF,
4993 "Schemas: group %s reference %s is not found",
4994 name, type->ref);
4995 return;
4996 }
4997 xmlSchemaBuildAContentModel(rgroup, ctxt, name);
4998 break;
4999 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005000 }
5001 case XML_SCHEMA_TYPE_COMPLEX:
5002 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5003 if (type->subtypes != NULL)
5004 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
5005 break;
5006 default:
5007 xmlGenericError(xmlGenericErrorContext,
5008 "Found unexpected type %d in %s content model\n",
5009 type->type, name);
5010 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005011 }
5012}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005013
Daniel Veillard4255d502002-04-16 15:50:10 +00005014/**
5015 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005016 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00005017 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005018 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00005019 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005020 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00005021 */
5022static void
5023xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005024 xmlSchemaParserCtxtPtr ctxt,
5025 const xmlChar * name)
5026{
Daniel Veillard4255d502002-04-16 15:50:10 +00005027 xmlAutomataStatePtr start;
5028
Daniel Veillard4255d502002-04-16 15:50:10 +00005029 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005030 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00005031 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005032 elem->contentType = XML_SCHEMA_CONTENT_ANY;
5033 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00005034 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005035 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005036 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005037 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
5038 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005039 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005040
5041#ifdef DEBUG_CONTENT
5042 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005043 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005044#endif
5045
Daniel Veillard4255d502002-04-16 15:50:10 +00005046 ctxt->am = xmlNewAutomata();
5047 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005048 xmlGenericError(xmlGenericErrorContext,
5049 "Cannot create automata for elem %s\n", name);
5050 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005051 }
5052 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
5053 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
5054 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00005055 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005056 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005057 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
5058 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005059 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005060 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
5061 "Content model of %s is not determinist:\n", name,
5062 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00005063 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00005064#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005065 xmlGenericError(xmlGenericErrorContext,
5066 "Content model of %s:\n", name);
5067 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005068#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00005069 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005070 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005071 xmlFreeAutomata(ctxt->am);
5072 ctxt->am = NULL;
5073}
5074
5075/**
5076 * xmlSchemaRefFixupCallback:
5077 * @elem: the schema element context
5078 * @ctxt: the schema parser context
5079 *
5080 * Free the resources associated to the schema parser context
5081 */
5082static void
5083xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005084 xmlSchemaParserCtxtPtr ctxt,
5085 const xmlChar * name,
5086 const xmlChar * context ATTRIBUTE_UNUSED,
5087 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005088{
5089 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005090 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00005091
Daniel Veillard4255d502002-04-16 15:50:10 +00005092 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005093 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005094
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005095 if (elem->subtypes != NULL) {
5096 xmlSchemaPErr(ctxt, elem->node,
5097 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
Daniel Veillard3646d642004-06-02 19:19:14 +00005098 "Schemas: element %s has both ref and subtype\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005099 name, NULL);
5100 return;
5101 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005102 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005103
5104 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005105 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
5106 "Schemas: element %s ref to %s not found\n",
5107 name, elem->ref);
5108 return;
5109 }
5110 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005111 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005112 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005113
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005114 if (elem->subtypes != NULL) {
5115 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
Daniel Veillard3646d642004-06-02 19:19:14 +00005116 "Schemas: element %s has both type and subtype\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005117 name, NULL);
5118 return;
5119 }
5120 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
5121 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00005122
5123 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005124 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
5125 "Schemas: element %s type %s not found\n", name,
5126 elem->namedType);
5127 return;
5128 }
5129 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005130 }
5131}
5132
William M. Bracke7091952004-05-11 15:09:58 +00005133/**
5134 * xmlSchemaParseListRefFixup:
5135 * @type: the schema type definition
5136 * @ctxt: the schema parser context
5137 *
5138 * Fixup of the itemType reference of the list type.
5139 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00005140static void
William M. Bracke7091952004-05-11 15:09:58 +00005141xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
5142{
5143 const xmlChar *itemType, *namespace;
5144 xmlSchemaTypePtr subtype;
5145
5146 /* Handle the "itemType" attribute. */
William M. Brack29aa7722004-05-12 00:27:56 +00005147 itemType = xmlGetQNameProp(ctxt, type->node, "itemType", &namespace);
William M. Bracke7091952004-05-11 15:09:58 +00005148 if (itemType != NULL) {
5149 /* Do not allow more that one item type. */
5150 if (type->subtypes != NULL) {
5151 xmlSchemaPErr(ctxt, type->node,
5152 XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE,
5153 "List %s has more than one item type defined\n",
5154 type->name, NULL);
5155 }
5156 subtype = xmlSchemaGetType(ctxt->schema, itemType, namespace);
5157 if (subtype == NULL) {
5158 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_TYPE,
5159 "List %s references an unknown item type: %s\n",
5160 type->name, xmlSchemaGetProp(ctxt, type->node,
William M. Brack29aa7722004-05-12 00:27:56 +00005161 "itemType"));
William M. Bracke7091952004-05-11 15:09:58 +00005162 } else
5163 type->subtypes = subtype;
5164 }
5165}
5166
5167/**
5168 * xmlSchemaParseUnionRefCheck:
5169 * @typeDecl: the schema type definition
5170 * @ctxt: the schema parser context
5171 *
5172 * Checks the memberTypes references of the union type.
5173 */
5174static void
5175xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00005176 xmlSchemaParserCtxtPtr ctxt)
5177{
5178 const xmlChar *cur, *end, *prefix, *ncName, *namespace;
5179 xmlChar *tmp;
5180 xmlSchemaTypePtr subtype;
5181 xmlNsPtr ns;
5182 int len;
5183
William M. Bracke7091952004-05-11 15:09:58 +00005184 if ((type->type != XML_SCHEMA_TYPE_UNION) || (type->ref == NULL))
Daniel Veillard377e1a92004-04-16 16:30:05 +00005185 return;
5186
William M. Bracke7091952004-05-11 15:09:58 +00005187 cur = type->ref;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005188 do {
5189 while (IS_BLANK_CH(*cur))
5190 cur++;
5191 end = cur;
5192 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5193 end++;
5194 if (end == cur)
5195 break;
5196 tmp = xmlStrndup(cur, end - cur);
5197 ncName = xmlSplitQName3(tmp, &len);
5198 if (ncName != NULL) {
5199 prefix = xmlDictLookup(ctxt->dict, tmp, len);
5200 } else {
5201 prefix = NULL;
5202 ncName = tmp;
5203 }
William M. Bracke7091952004-05-11 15:09:58 +00005204 ns = xmlSearchNs(type->node->doc, type->node, prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005205 if (ns == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005206 if (prefix != NULL) {
5207 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_PREFIX_UNDEFINED,
5208 "Union %s: the namespace prefix of member type "
5209 "%s is undefined\n",
5210 type->name, (const xmlChar *) tmp);
5211 }
5212 namespace = NULL;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005213 } else {
5214 namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
5215 }
5216 /* Lookup the referenced type */
5217 subtype = xmlSchemaGetType(ctxt->schema, ncName, namespace);
5218 if (subtype == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005219 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
5220 "Union %s references an unknown member type %s\n",
5221 type->name, (const xmlChar *) tmp);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005222 }
William M. Bracke7091952004-05-11 15:09:58 +00005223 xmlFree(tmp);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005224 cur = end;
William M. Bracke7091952004-05-11 15:09:58 +00005225 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005226}
5227
Daniel Veillard4255d502002-04-16 15:50:10 +00005228/**
Daniel Veillard3646d642004-06-02 19:19:14 +00005229 * xmlSchemaGetOnymousTypeName:
5230 * @attr: the attribute declaration/use
5231 *
5232 * Returns the name of the attribute; if the attribute
5233 * is a reference, the name of the referenced global type will be returned.
5234 */
5235static const xmlChar *
5236xmlSchemaGetOnymousAttrName(xmlSchemaAttributePtr attr)
5237{
5238 if (attr->ref != NULL)
5239 return(attr->ref);
5240 else
5241 return(attr->name);
5242}
5243
5244/**
5245 * xmlSchemaGetOnymousTargetNsURI:
5246 * @type: the type (element or attribute)
5247 *
5248 * Returns the target namespace URI of the type; if the type is a reference,
5249 * the target namespace of the referenced type will be returned.
5250 */
5251static const xmlChar *
5252xmlSchemaGetOnymousTargetNsURI(xmlSchemaTypePtr type)
5253{
5254 if (type->type == XML_SCHEMA_TYPE_ELEMENT) {
5255 if (type->ref != NULL)
5256 return(((xmlSchemaElementPtr)((xmlSchemaElementPtr)
5257 type)->subtypes)->targetNamespace);
5258 else
5259 return(((xmlSchemaElementPtr) type)->targetNamespace);
5260 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
5261 if (type->ref != NULL)
5262 return(((xmlSchemaAttributePtr)((xmlSchemaAttributePtr)
5263 type)->subtypes)->targetNamespace);
5264 else
5265 return(((xmlSchemaAttributePtr) type)->targetNamespace);
5266 } else
5267 return (NULL);
5268}
5269
5270/**
5271 * xmlSchemaIsDerivedFromBuiltInType:
5272 * @ctxt: the schema parser context
5273 * @type: the type definition
5274 * @valType: the value type
5275 *
5276 *
5277 * Returns 1 if the type has the given value type, or
5278 * is derived from such a type.
5279 */
William M. Brack803812b2004-06-03 02:11:24 +00005280static int
Daniel Veillard3646d642004-06-02 19:19:14 +00005281xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
5282 xmlSchemaTypePtr type, int valType)
5283{
5284 /* TODO: Check if this works in every case. */
5285 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
5286 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
5287 if (type->flags == valType)
5288 return(1);
5289 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
5290 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
5291 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
5292 ((xmlSchemaAttributePtr) type)->subtypes, valType));
5293 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
5294 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
5295 if (type->baseType != NULL)
5296 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
5297 valType));
5298 } else if ((type->subtypes != NULL) &&
5299 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
5300 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
5301 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
5302 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
5303 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
5304 valType));
5305 }
5306
5307 return (0);
5308}
5309
5310/**
5311 * xmlSchemaBuildAttributeUsesOwned:
5312 * @ctxt: the schema parser context
5313 * @type: the complex type definition
5314 * @cur: the attribute declaration list
5315 * @lastUse: the top of the attribute use list
5316 *
5317 * Builds the attribute uses list on the given complex type.
5318 * This one is supposed to be called by
5319 * xmlSchemaBuildAttributeValidation only.
5320 */
5321static int
5322xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
5323 xmlSchemaAttributePtr cur,
5324 xmlSchemaAttributeLinkPtr *uses,
5325 xmlSchemaAttributeLinkPtr *lastUse)
5326{
5327 xmlSchemaAttributeLinkPtr tmp;
5328 while (cur != NULL) {
5329 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5330 /*
5331 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
5332 * to by the ·actual value·s of the ref [attribute] of the
5333 * <attributeGroup> [children], if any."
5334 */
5335 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
5336 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
5337 lastUse) == -1) {
5338 return (-1);
5339 }
5340 } else {
5341 /* W3C: "1 The set of attribute uses corresponding to the
5342 * <attribute> [children], if any."
5343 */
5344 tmp = (xmlSchemaAttributeLinkPtr)
5345 xmlMalloc(sizeof(xmlSchemaAttributeLink));
5346 if (tmp == NULL) {
5347 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
5348 return (-1);
5349 }
5350 tmp->attr = cur;
5351 tmp->next = NULL;
5352 if (*uses == NULL)
5353 *uses = tmp;
5354 else
5355 (*lastUse)->next = tmp;
5356 *lastUse = tmp;
5357 }
5358 cur = cur->next;
5359 }
5360 return (0);
5361}
5362
Daniel Veillard50355f02004-06-08 17:52:16 +00005363/**
5364 * xmlSchemaCloneWildcardNsConstraints:
5365 * @ctxt: the schema parser context
5366 * @dest: the destination wildcard
5367 * @source: the source wildcard
5368 *
5369 * Clones the namespace constraints of source
5370 * and assignes them to dest.
5371 * Returns -1 on internal error, 0 otherwise.
5372 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005373static int
5374xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
5375 xmlSchemaWildcardPtr *dest,
5376 xmlSchemaWildcardPtr source)
5377{
5378 xmlSchemaWildcardNsPtr cur, tmp, last;
5379
5380 if ((source == NULL) || (*dest == NULL))
5381 return(-1);
5382 (*dest)->any = source->any;
5383 cur = source->nsSet;
5384 last = NULL;
5385 while (cur != NULL) {
5386 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5387 if (tmp == NULL)
5388 return(-1);
5389 tmp->value = cur->value;
5390 if (last == NULL)
5391 (*dest)->nsSet = tmp;
5392 else
5393 last->next = tmp;
5394 last = tmp;
5395 cur = cur->next;
5396 }
5397 if ((*dest)->negNsSet != NULL)
5398 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
5399 if (source->negNsSet != NULL) {
5400 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5401 if ((*dest)->negNsSet == NULL)
5402 return(-1);
5403 (*dest)->negNsSet->value = source->negNsSet->value;
5404 } else
5405 (*dest)->negNsSet = NULL;
5406 return(0);
5407}
5408
Daniel Veillard50355f02004-06-08 17:52:16 +00005409/**
5410 * xmlSchemaUnionWildcards:
5411 * @ctxt: the schema parser context
5412 * @completeWild: the first wildcard
5413 * @curWild: the second wildcard
5414 *
5415 * Unions the namespace constraints of the given wildcards.
5416 * @completeWild will hold the resulting union.
5417 * Returns a positive error code on failure, -1 in case of an
5418 * internal error, 0 otherwise.
5419 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005420static int
5421xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
5422 xmlSchemaWildcardPtr completeWild,
5423 xmlSchemaWildcardPtr curWild)
5424{
5425 xmlSchemaWildcardNsPtr cur, curB, tmp;
5426
5427 /*
5428 * 1 If O1 and O2 are the same value, then that value must be the
5429 * value.
5430 */
5431 if ((completeWild->any == curWild->any) &&
5432 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
5433 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
5434
5435 if ((completeWild->negNsSet == NULL) ||
5436 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
5437
5438 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00005439 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00005440
5441 /*
5442 * Check equality of sets.
5443 */
5444 cur = completeWild->nsSet;
5445 while (cur != NULL) {
5446 found = 0;
5447 curB = curWild->nsSet;
5448 while (curB != NULL) {
5449 if (cur->value == curB->value) {
5450 found = 1;
5451 break;
5452 }
5453 curB = curB->next;
5454 }
5455 if (!found)
5456 break;
5457 cur = cur->next;
5458 }
5459 if (found)
5460 return(0);
5461 } else
5462 return(0);
5463 }
5464 }
5465 /*
5466 * 2 If either O1 or O2 is any, then any must be the value
5467 */
Daniel Veillard50355f02004-06-08 17:52:16 +00005468 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005469 if (completeWild->any == 0) {
5470 completeWild->any = 1;
5471 if (completeWild->nsSet != NULL) {
5472 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5473 completeWild->nsSet = NULL;
5474 }
5475 if (completeWild->negNsSet != NULL) {
5476 xmlFree(completeWild->negNsSet);
5477 completeWild->negNsSet = NULL;
5478 }
5479 }
Daniel Veillard50355f02004-06-08 17:52:16 +00005480 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00005481 }
5482 /*
5483 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
5484 * then the union of those sets must be the value.
5485 */
5486 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
5487 int found;
5488 xmlSchemaWildcardNsPtr start;
5489
5490 cur = curWild->nsSet;
5491 start = completeWild->nsSet;
5492 while (cur != NULL) {
5493 found = 0;
5494 curB = start;
5495 while (curB != NULL) {
5496 if (cur->value == curB->value) {
5497 found = 1;
5498 break;
5499 }
5500 curB = curB->next;
5501 }
5502 if (!found) {
5503 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5504 if (tmp == NULL)
5505 return (-1);
5506 tmp->value = cur->value;
5507 tmp->next = completeWild->nsSet;
5508 completeWild->nsSet = tmp;
5509 }
5510 cur = cur->next;
5511 }
5512
5513 return(0);
5514 }
5515 /*
5516 * 4 If the two are negations of different values (namespace names
5517 * or ·absent·), then a pair of not and ·absent· must be the value.
5518 */
5519 if ((completeWild->negNsSet != NULL) &&
5520 (curWild->negNsSet != NULL) &&
5521 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
5522 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00005523
5524 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00005525 }
5526 /*
5527 * 5.
5528 */
5529 if (((completeWild->negNsSet != NULL) &&
5530 (completeWild->negNsSet->value != NULL) &&
5531 (curWild->nsSet != NULL)) ||
5532 ((curWild->negNsSet != NULL) &&
5533 (curWild->negNsSet->value != NULL) &&
5534 (completeWild->nsSet != NULL))) {
5535
5536 int nsFound, absentFound = 0;
5537
5538 if (completeWild->nsSet != NULL) {
5539 cur = completeWild->nsSet;
5540 curB = curWild->negNsSet;
5541 } else {
5542 cur = curWild->nsSet;
5543 curB = completeWild->negNsSet;
5544 }
5545 nsFound = 0;
5546 while (cur != NULL) {
5547 if (cur->value == NULL)
5548 absentFound = 1;
5549 else if (cur->value == curB->value)
5550 nsFound = 1;
5551 if (nsFound && absentFound)
5552 break;
5553 cur = cur->next;
5554 }
5555
5556 if (nsFound && absentFound) {
5557 /*
5558 * 5.1 If the set S includes both the negated namespace
5559 * name and ·absent·, then any must be the value.
5560 */
5561 completeWild->any = 1;
5562 if (completeWild->nsSet != NULL) {
5563 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5564 completeWild->nsSet = NULL;
5565 }
5566 if (completeWild->negNsSet != NULL) {
5567 xmlFree(completeWild->negNsSet);
5568 completeWild->negNsSet = NULL;
5569 }
5570 } else if (nsFound && (!absentFound)) {
5571 /*
5572 * 5.2 If the set S includes the negated namespace name
5573 * but not ·absent·, then a pair of not and ·absent· must
5574 * be the value.
5575 */
5576 if (completeWild->nsSet != NULL) {
5577 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5578 completeWild->nsSet = NULL;
5579 }
5580 if (completeWild->negNsSet == NULL) {
5581 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5582 if (completeWild->negNsSet == NULL)
5583 return (-1);
5584 }
5585 completeWild->negNsSet->value = NULL;
5586 } else if ((!nsFound) && absentFound) {
5587 /*
5588 * 5.3 If the set S includes ·absent· but not the negated
5589 * namespace name, then the union is not expressible.
5590 */
5591 xmlSchemaPErr(ctxt, completeWild->node,
5592 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
5593 "The union of the wilcard is not expressible\n",
5594 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00005595 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00005596 } else if ((!nsFound) && (!absentFound)) {
5597 /*
5598 * 5.4 If the set S does not include either the negated namespace
5599 * name or ·absent·, then whichever of O1 or O2 is a pair of not
5600 * and a namespace name must be the value.
5601 */
5602 if (completeWild->negNsSet == NULL) {
5603 if (completeWild->nsSet != NULL) {
5604 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5605 completeWild->nsSet = NULL;
5606 }
5607 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5608 if (completeWild->negNsSet == NULL)
5609 return (-1);
5610 completeWild->negNsSet->value = curWild->negNsSet->value;
5611 }
5612 }
5613 return (0);
5614 }
5615 /*
5616 * 6.
5617 */
5618 if (((completeWild->negNsSet != NULL) &&
5619 (completeWild->negNsSet->value == NULL) &&
5620 (curWild->nsSet != NULL)) ||
5621 ((curWild->negNsSet != NULL) &&
5622 (curWild->negNsSet->value == NULL) &&
5623 (completeWild->nsSet != NULL))) {
5624
5625 if (completeWild->nsSet != NULL) {
5626 cur = completeWild->nsSet;
5627 } else {
5628 cur = curWild->nsSet;
5629 }
5630 while (cur != NULL) {
5631 if (cur->value == NULL) {
5632 /*
5633 * 6.1 If the set S includes ·absent·, then any must be the
5634 * value.
5635 */
5636 completeWild->any = 1;
5637 if (completeWild->nsSet != NULL) {
5638 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5639 completeWild->nsSet = NULL;
5640 }
5641 if (completeWild->negNsSet != NULL) {
5642 xmlFree(completeWild->negNsSet);
5643 completeWild->negNsSet = NULL;
5644 }
5645 return (0);
5646 }
5647 cur = cur->next;
5648 }
5649 if (completeWild->negNsSet == NULL) {
5650 /*
5651 * 6.2 If the set S does not include ·absent·, then a pair of not
5652 * and ·absent· must be the value.
5653 */
5654 if (completeWild->nsSet != NULL) {
5655 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5656 completeWild->nsSet = NULL;
5657 }
5658 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5659 if (completeWild->negNsSet == NULL)
5660 return (-1);
5661 completeWild->negNsSet->value = NULL;
5662 }
5663 return (0);
5664 }
5665 return (0);
5666
5667}
5668
Daniel Veillard50355f02004-06-08 17:52:16 +00005669/**
5670 * xmlSchemaIntersectWildcards:
5671 * @ctxt: the schema parser context
5672 * @completeWild: the first wildcard
5673 * @curWild: the second wildcard
5674 *
5675 * Intersects the namespace constraints of the given wildcards.
5676 * @completeWild will hold the resulting intersection.
5677 * Returns a positive error code on failure, -1 in case of an
5678 * internal error, 0 otherwise.
5679 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005680static int
5681xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
5682 xmlSchemaWildcardPtr completeWild,
5683 xmlSchemaWildcardPtr curWild)
5684{
William M. Brack803812b2004-06-03 02:11:24 +00005685 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00005686
5687 /*
5688 * 1 If O1 and O2 are the same value, then that value must be the
5689 * value.
5690 */
5691 if ((completeWild->any == curWild->any) &&
5692 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
5693 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
5694
5695 if ((completeWild->negNsSet == NULL) ||
5696 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
5697
5698 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00005699 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00005700
5701 /*
5702 * Check equality of sets.
5703 */
5704 cur = completeWild->nsSet;
5705 while (cur != NULL) {
5706 found = 0;
5707 curB = curWild->nsSet;
5708 while (curB != NULL) {
5709 if (cur->value == curB->value) {
5710 found = 1;
5711 break;
5712 }
5713 curB = curB->next;
5714 }
5715 if (!found)
5716 break;
5717 cur = cur->next;
5718 }
5719 if (found)
5720 return(0);
5721 } else
5722 return(0);
5723 }
5724 }
5725 /*
5726 * 2 If either O1 or O2 is any, then the other must be the value.
5727 */
5728 if ((completeWild->any != curWild->any) && (completeWild->any)) {
5729 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
5730 return(-1);
5731 return(0);
5732 }
5733 /*
5734 * 3 If either O1 or O2 is a pair of not and a value (a namespace
5735 * name or ·absent·) and the other is a set of (namespace names or
5736 * ·absent·), then that set, minus the negated value if it was in
5737 * the set, minus ·absent· if it was in the set, must be the value.
5738 */
5739 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
5740 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
5741 const xmlChar *neg;
5742
5743 if (completeWild->nsSet == NULL) {
5744 neg = completeWild->negNsSet->value;
5745 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
5746 return(-1);
5747 } else
5748 neg = curWild->negNsSet->value;
5749 /*
5750 * Remove absent and negated.
5751 */
5752 prev = NULL;
5753 cur = completeWild->nsSet;
5754 while (cur != NULL) {
5755 if (cur->value == NULL) {
5756 if (prev == NULL)
5757 completeWild->nsSet = cur->next;
5758 else
5759 prev->next = cur->next;
5760 xmlFree(cur);
5761 break;
5762 }
5763 prev = cur;
5764 cur = cur->next;
5765 }
5766 if (neg != NULL) {
5767 prev = NULL;
5768 cur = completeWild->nsSet;
5769 while (cur != NULL) {
5770 if (cur->value == neg) {
5771 if (prev == NULL)
5772 completeWild->nsSet = cur->next;
5773 else
5774 prev->next = cur->next;
5775 xmlFree(cur);
5776 break;
5777 }
5778 prev = cur;
5779 cur = cur->next;
5780 }
5781 }
5782
5783 return(0);
5784 }
5785 /*
5786 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
5787 * then the intersection of those sets must be the value.
5788 */
5789 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
5790 int found;
5791
5792 cur = completeWild->nsSet;
5793 prev = NULL;
5794 while (cur != NULL) {
5795 found = 0;
5796 curB = curWild->nsSet;
5797 while (curB != NULL) {
5798 if (cur->value == curB->value) {
5799 found = 1;
5800 break;
5801 }
5802 curB = curB->next;
5803 }
5804 if (!found) {
5805 if (prev == NULL)
5806 completeWild->nsSet = cur->next;
5807 else
5808 prev->next = cur->next;
5809 tmp = cur->next;
5810 xmlFree(cur);
5811 cur = tmp;
5812 continue;
5813 }
5814 prev = cur;
5815 cur = cur->next;
5816 }
5817
5818 return(0);
5819 }
5820 /* 5 If the two are negations of different namespace names,
5821 * then the intersection is not expressible
5822 */
5823 if ((completeWild->negNsSet != NULL) &&
5824 (curWild->negNsSet != NULL) &&
5825 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
5826 (completeWild->negNsSet->value != NULL) &&
5827 (curWild->negNsSet->value != NULL)) {
5828
5829 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
5830 "The intersection of the wilcard is not expressible\n",
5831 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00005832 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00005833 }
5834 /*
5835 * 6 If the one is a negation of a namespace name and the other
5836 * is a negation of ·absent·, then the one which is the negation
5837 * of a namespace name must be the value.
5838 */
5839 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
5840 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
5841 (completeWild->negNsSet->value == NULL)) {
5842 completeWild->negNsSet->value = curWild->negNsSet->value;
5843 }
5844 return(0);
5845}
5846
Daniel Veillard50355f02004-06-08 17:52:16 +00005847/**
5848 * xmlSchemaIsWildcardNsConstraintSubset:
5849 * @ctxt: the schema parser context
5850 * @wildA: the first wildcard
5851 * @wildB: the second wildcard
5852 *
5853 * Returns 1 if the namespace constraint of @wildA is an intensional
5854 * subset of @wildB, 0 otherwise.
5855 */
5856static int
5857xmlSchemaIsWildcardNsConstraintSubset(
5858 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
5859 xmlSchemaWildcardPtr wildA,
5860 xmlSchemaWildcardPtr wildB)
5861{
Daniel Veillard3646d642004-06-02 19:19:14 +00005862
Daniel Veillard50355f02004-06-08 17:52:16 +00005863 /*
5864 * Schema Component Constraint: Wildcard Subset
5865 */
5866 /*
5867 * 1 super must be any.
5868 */
5869 if (wildB->any)
5870 return (1);
5871 /*
5872 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
5873 * 2.2 super must be a pair of not and the same value.
5874 */
5875 if ((wildA->negNsSet != NULL) &&
5876 (wildB->negNsSet != NULL) &&
5877 (wildA->negNsSet->value == wildA->negNsSet->value))
5878 return (1);
5879 /*
5880 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
5881 */
5882 if (wildA->nsSet != NULL) {
5883 /*
5884 * 3.2.1 super must be the same set or a superset thereof.
5885 */
5886 if (wildB->nsSet != NULL) {
5887 xmlSchemaWildcardNsPtr cur, curB;
5888 int found = 0;
5889
5890 cur = wildA->nsSet;
5891 while (cur != NULL) {
5892 found = 0;
5893 curB = wildB->nsSet;
5894 while (curB != NULL) {
5895 if (cur->value == curB->value) {
5896 found = 1;
5897 break;
5898 }
5899 curB = curB->next;
5900 }
5901 if (!found)
5902 return (0);
5903 cur = cur->next;
5904 }
5905 if (found)
5906 return (1);
5907 } else if (wildB->negNsSet != NULL) {
5908 xmlSchemaWildcardNsPtr cur;
5909 /*
5910 * 3.2.2 super must be a pair of not and a namespace name or
5911 * ·absent· and that value must not be in sub's set.
5912 */
5913 cur = wildA->nsSet;
5914 while (cur != NULL) {
5915 if (cur->value == wildB->negNsSet->value)
5916 return (0);
5917 cur = cur->next;
5918 }
5919 return (1);
5920 }
5921 }
5922 return (0);
5923}
5924
5925/**
5926 * xmlSchemaBuildCompleteAttributeWildcard:
5927 * @ctxt: the schema parser context
5928 * @attrs: the attribute list
5929 * @completeWild: the resulting complete wildcard
5930 *
5931 * Returns -1 in case of an internal error, 0 otherwise.
5932 */
5933static int
5934xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
5935 xmlSchemaAttributePtr attrs,
5936 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00005937{
5938 while (attrs != NULL) {
5939 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5940 xmlSchemaAttributeGroupPtr group;
5941
5942 group = (xmlSchemaAttributeGroupPtr) attrs;
5943 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
5944 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00005945 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
5946 group->attributes, &group->attributeWildcard) == -1)
5947 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00005948 }
5949 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
5950 }
5951 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00005952 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005953 /*
5954 * Copy the first encountered wildcard as context, except for the annotation.
5955 */
Daniel Veillard50355f02004-06-08 17:52:16 +00005956 *completeWild = xmlSchemaAddWildcard(ctxt);
5957 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
5958 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
5959 completeWild, group->attributeWildcard) == -1)
5960 return (-1);
5961 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00005962 /*
5963 * Although the complete wildcard might not correspond to any
5964 * node in the schema, we will save this context node.
5965 */
Daniel Veillard50355f02004-06-08 17:52:16 +00005966 (*completeWild)->node = group->attributeWildcard->node;
5967
5968 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
5969 xmlSchemaFreeWildcard(*completeWild);
5970 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00005971 }
5972 }
5973 }
5974 attrs = attrs->next;
5975 }
5976
Daniel Veillard50355f02004-06-08 17:52:16 +00005977 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00005978}
5979
5980/**
5981 * xmlSchemaMatchesWildcardNs:
5982 * @wild: the wildcard
5983 * @ns: the namespace
5984 *
5985 *
5986 * Returns 1 if the given namespace matches the wildcard,
5987 * 0 otherwise.
5988 */
5989static int
5990xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
5991{
5992 if (wild == NULL)
5993 return(0);
5994
5995 if (wild->any)
5996 return(1);
5997 else if (wild->nsSet != NULL) {
5998 xmlSchemaWildcardNsPtr cur;
5999
6000 cur = wild->nsSet;
6001 while (cur != NULL) {
6002 if (xmlStrEqual(cur->value, ns))
6003 return(1);
6004 cur = cur->next;
6005 }
6006 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
6007 (!xmlStrEqual(wild->negNsSet->value, ns)))
6008 return(1);
6009
6010 return(0);
6011}
6012
6013/**
6014 * xmlSchemaBuildAttributeValidation:
6015 * @ctxt: the schema parser context
6016 * @type: the complex type definition
6017 *
6018 *
6019 * Builds the wildcard and the attribute uses on the given complex type.
6020 * Returns -1 if an internal error occurs, 0 otherwise.
6021 */
6022static int
6023xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
6024{
6025 xmlSchemaTypePtr baseType = NULL;
6026 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +00006027 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00006028 xmlSchemaAttributePtr attrs;
Daniel Veillard50355f02004-06-08 17:52:16 +00006029 int baseIsAnyType = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00006030
6031 /*
6032 * Complex Type Definition with complex content Schema Component.
6033 *
6034 * Attribute uses.
6035 */
6036 if (type->attributeUses != NULL) {
6037 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
6038 "Internal error: xmlSchemaParseBuildAttributeUses: "
6039 "attribute uses already builded.\n",
6040 NULL, NULL);
6041 return (-1);
6042 }
6043 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) ||
6044 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Daniel Veillard50355f02004-06-08 17:52:16 +00006045
Daniel Veillard3646d642004-06-02 19:19:14 +00006046 /*
6047 * Inherit the attribute uses of the base type.
6048 */
6049 baseType = type->subtypes->subtypes->baseType;
6050 /*
6051 * TODO: URGENT: This is not nice, but currently
6052 * xmlSchemaTypeAnyTypeDef is static in xmlschematypes.c.
6053 */
6054 if ((baseType->type == XML_SCHEMA_TYPE_BASIC) &&
William M. Brack803812b2004-06-03 02:11:24 +00006055 xmlStrEqual(baseType->name, BAD_CAST "anyType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006056 baseIsAnyType = 1;
6057 }
6058 /*
6059 * TODO: Does the spec state that it is an error to "extend" the
6060 * anyType?
6061 */
6062 if (!baseIsAnyType) {
6063 if (baseType != NULL) {
6064 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
6065 tmp = (xmlSchemaAttributeLinkPtr)
6066 xmlMalloc(sizeof(xmlSchemaAttributeLink));
6067 if (tmp == NULL) {
6068 xmlSchemaPErrMemory(ctxt,
6069 "building attribute uses of complexType", NULL);
6070 return (-1);
6071 }
6072 tmp->attr = cur->attr;
6073 tmp->next = NULL;
6074 if (type->attributeUses == NULL) {
6075 type->attributeUses = tmp;
6076 } else
6077 lastBaseUse->next = tmp;
6078 lastBaseUse = tmp;
6079 }
6080 }
6081 }
6082 attrs = type->subtypes->subtypes->attributes;
6083 /*
6084 * Handle attribute wildcards.
Daniel Veillard50355f02004-06-08 17:52:16 +00006085 */
6086 type->attributeWildcard = type->subtypes->subtypes->attributeWildcard;
6087
6088 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
6089 attrs, &type->attributeWildcard) == -1) {
6090 if ((type->attributeWildcard != NULL) &&
6091 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard))
6092 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6093 return (-1);
6094 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006095 if ((type->attributeWildcard != NULL) &&
6096 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard))
6097 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6098
6099 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
6100 (baseType != NULL) && (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
6101 (baseType->attributeWildcard != NULL)) {
6102 if (type->attributeWildcard != NULL) {
6103 /*
6104 * Union the complete wildcard with the base wildcard.
6105 */
6106 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
6107 baseType->attributeWildcard) == -1)
6108 return (-1);
6109 } else {
6110 /*
6111 * Just inherit the wildcard.
6112 */
6113 type->attributeWildcard = baseType->attributeWildcard;
6114 }
6115 }
Daniel Veillard50355f02004-06-08 17:52:16 +00006116 if (!baseIsAnyType) {
6117 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
6118 if (type->attributeWildcard != NULL) {
6119 /*
6120 * Derivation Valid (Restriction, Complex)
6121 * 4.1 The {base type definition} must also have one.
6122 */
6123 if (baseType->attributeWildcard == NULL) {
6124 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
6125 "The derived type \"%s\" has an attribute wildcard, "
6126 "but the base type \"%s\" does not have one.\n",
6127 type->name, baseType->name);
6128 return (1);
6129 } else if (xmlSchemaIsWildcardNsConstraintSubset(ctxt,
6130 type->attributeWildcard, baseType->attributeWildcard) == 0) {
6131 /* 4.2 */
6132 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
6133 "The wildcard in the derived type \"%s\" is not a valid "
6134 "subset of the one in the base type \"%s\".\n",
6135 type->name, baseType->name);
6136 return (1);
6137 }
6138 /* 4.3 Unless the {base type definition} is the ·ur-type
6139 * definition·, the complex type definition's {attribute
6140 * wildcard}'s {process contents} must be identical to or
6141 * stronger than the {base type definition}'s {attribute
6142 * wildcard}'s {process contents}, where strict is stronger
6143 * than lax is stronger than skip.
6144 */
6145 if (type->attributeWildcard->processContents <
6146 baseType->attributeWildcard->processContents) {
6147 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
6148 "The process contents of the wildcard in the "
6149 "derived type \"%s\" is weaker than "
6150 "that in the base type \"%s\".\n",
6151 type->name, baseType->name);
6152 return (1);
6153 }
6154 }
6155 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
6156 /*
6157 * Derivation Valid (Extension)
6158 * At this point the type and the base have both, either
6159 * no wildcard or a wildcard.
6160 */
6161 if ((baseType->attributeWildcard != NULL) &&
6162 (baseType->attributeWildcard != type->attributeWildcard)) {
6163 /* 1.3 */
6164 if (xmlSchemaIsWildcardNsConstraintSubset(ctxt,
6165 baseType->attributeWildcard, type->attributeWildcard) == 0) {
6166 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_COS_CT_EXTENDS_1_3,
6167 "The wildcard in the derived type \"%s\" is not a valid "
6168 "superset of the one in the base type \"%s\".\n",
6169 type->name, baseType->name);
6170 return (1);
6171 }
6172 }
6173 }
6174 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006175 } else {
6176 /*
6177 * Although the complexType is implicitely derived by "restriction"
6178 * from the ur-type, this is not (yet?) reflected by libxml2.
6179 */
6180 baseType = NULL;
6181 attrs = type->attributes;
Daniel Veillard50355f02004-06-08 17:52:16 +00006182 if (attrs != NULL) {
6183 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
6184 attrs, &type->attributeWildcard) == -1) {
6185 if ((type->attributeWildcard != NULL) &&
6186 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard))
6187 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6188 return (-1);
6189 }
6190 if ((type->attributeWildcard != NULL) &&
6191 ((type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD) == 0))
6192 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6193 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006194 }
6195 /*
6196 * Gather attribute uses defined by this type.
6197 */
6198 if (attrs != NULL) {
6199 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
6200 &uses, &lastUse) == -1) {
6201 return (-1);
6202 }
6203 }
6204 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
6205 * "Two distinct attribute declarations in the {attribute uses} must
6206 * not have identical {name}s and {target namespace}s."
6207 *
6208 * For "extension" this is done further down.
6209 */
6210 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
6211 cur = uses;
6212 while (cur != NULL) {
6213 tmp = cur->next;
6214 while (tmp != NULL) {
6215 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6216 xmlSchemaGetOnymousAttrName(tmp->attr))) &&
6217 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
6218 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
6219
6220 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
6221 "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
6222 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6223 break;
6224 }
6225 tmp = tmp->next;
6226 }
6227 cur = cur->next;
6228 }
6229 }
6230 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
6231 /*
6232 * Derive by restriction.
6233 */
6234 if (baseIsAnyType) {
6235 type->attributeUses = uses;
6236 } else {
6237 int found;
6238
6239 cur = uses;
6240 while (cur != NULL) {
6241 found = 0;
6242 base = type->attributeUses;
6243 while (base != NULL) {
6244 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6245 xmlSchemaGetOnymousAttrName(base->attr))) &&
6246 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr),
6247 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) base->attr)))) {
6248
6249 found = 1;
6250 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6251 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6252 /*
6253 * derivation-ok-restriction 2.1.1
6254 */
6255 xmlSchemaPErr(ctxt, cur->attr->node,
6256 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
6257 "derivation-ok-restriction.2.1.1: "
6258 "The \"optional\" attribute "
6259 "use \"%s\" is inconsistent with a matching "
6260 "\"required\" attribute use of the base type\n",
6261 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6262 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
6263 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6264 /*
6265 * derivation-ok-restriction 3
6266 */
6267 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
6268 "derivation-ok-restriction.3: "
6269 "The \"required\" attribute use \"%s\" of the base type "
6270 "does not have a matching attribute use in the derived type\n",
6271 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6272
6273 } else {
6274 /*
6275 * Override the attribute use.
6276 */
6277 base->attr = cur->attr;
6278 }
6279 /*
6280 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
Daniel Veillard50355f02004-06-08 17:52:16 +00006281 * TODO: derivation-ok-restriction 2.1.3
Daniel Veillard3646d642004-06-02 19:19:14 +00006282 */
6283 break;
6284 }
6285 base = base->next;
6286 }
6287
6288 if (!found) {
6289 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6290 /*
6291 * derivation-ok-restriction 2.2
6292 */
6293 if ((type->attributeWildcard != NULL) &&
6294 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
6295 cur->attr->targetNamespace))
6296 found = 1;
6297
6298 if (!found) {
6299 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
6300 "derivation-ok-restriction.2.2: "
6301 "The attribute use \"%s\" has neither a matching attribute use, "
6302 "nor a matching wildcard in the base type\n",
6303 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6304 } else {
6305 /*
6306 * Add the attribute use.
6307 *
6308 * Note that this may lead to funny derivation error reports, if
6309 * multiple equal attribute uses exist; but this is not
6310 * allowed anyway, and it will be reported beforehand.
6311 */
6312 tmp = cur;
6313 if (prev != NULL)
6314 prev->next = cur->next;
6315 else
6316 uses = cur->next;
6317 cur = cur->next;
6318 if (type->attributeUses == NULL) {
6319 type->attributeUses = tmp;
6320 } else
6321 lastBaseUse->next = tmp;
6322 lastBaseUse = tmp;
6323
6324 continue;
6325 }
6326 }
6327 }
6328 prev = cur;
6329 cur = cur->next;
6330 }
6331 if (uses != NULL)
6332 xmlSchemaFreeAttributeUseList(uses);
6333 }
6334 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
6335 /*
6336 * The spec allows only appending, and not other kinds of extensions.
6337 *
6338 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
6339 */
6340 if (uses != NULL) {
6341 if (type->attributeUses == NULL) {
6342 type->attributeUses = uses;
6343 } else
6344 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00006345 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006346 } else {
6347 /*
Daniel Veillard50355f02004-06-08 17:52:16 +00006348 * Derive implicitely from the ur-type.
6349 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006350 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00006351 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006352 /*
6353 * 3.4.6 -> Complex Type Definition Properties Correct
6354 */
6355 if (type->attributeUses != NULL) {
6356 cur = type->attributeUses;
6357 prev = NULL;
6358 while (cur != NULL) {
6359 /*
6360 * 4. Two distinct attribute declarations in the {attribute uses} must
6361 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +00006362 *
Daniel Veillard3646d642004-06-02 19:19:14 +00006363 * Note that this was already done for "restriction" and types derived from
6364 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +00006365 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006366 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
6367 tmp = cur->next;
6368 while (tmp != NULL) {
6369 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6370 xmlSchemaGetOnymousAttrName(tmp->attr))) &&
6371 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
6372 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
6373
6374 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
6375 "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
6376 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00006377 break;
6378 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006379 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00006380 }
6381 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006382 /*
6383 * 5. Two distinct attribute declarations in the {attribute uses} must
6384 * not have {type definition}s which are or are derived from ID.
6385 */
6386 if ((cur->attr->subtypes != NULL) &&
6387 /*
6388 * TODO: FIXME: XML_SCHEMAS_ID should be used instead of "23" !!!,
6389 * but the xmlSchemaValType is not made public yet.
6390 */
6391 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, 23))) {
6392 if (id != NULL) {
6393 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_5,
6394 "ct-props-correct.5: Two attribute declarations, "
6395 "\"%s\" and \"%s\" have types which derived from ID\n",
6396 xmlSchemaGetOnymousAttrName(id->attr),
6397 xmlSchemaGetOnymousAttrName(cur->attr));
Daniel Veillard50355f02004-06-08 17:52:16 +00006398 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006399 id = cur;
6400 }
6401 /*
6402 * Remove "prohibited" attribute uses. The reason this is done at this late
6403 * stage is to be able to catch dublicate attribute uses. So we had to keep
6404 * prohibited uses in the list as well.
6405 */
6406 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6407 tmp = cur;
6408 if (prev == NULL)
6409 type->attributeUses = cur->next;
6410 else
6411 prev->next = cur->next;
6412 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00006413 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +00006414 } else {
6415 prev = cur;
6416 cur = cur->next;
6417 }
6418 }
6419 }
6420 /*
6421 * TODO: This check should be removed if we are 100% sure of
6422 * the base type attribute uses already being built.
6423 */
6424 if ((baseType != NULL) && (!baseIsAnyType) &&
6425 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
6426 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
6427 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAS_ERR_INTERNAL,
6428 "Internal error: xmlSchemaParseBuildAttributeUses: "
6429 "attribute uses not builded on base type \"%s\".\n",
6430 baseType->name, NULL);
6431 }
6432 return (0);
6433}
6434
6435/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006436 * xmlSchemaTypeFixup:
6437 * @typeDecl: the schema type definition
6438 * @ctxt: the schema parser context
6439 *
6440 * Fixes the content model of the type.
6441 */
6442static void
6443xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006444 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00006445{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006446 if (typeDecl == NULL)
6447 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006448 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006449 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006450 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006451 switch (typeDecl->type) {
6452 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
6453 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
6454 if (typeDecl->subtypes != NULL)
6455 typeDecl->contentType =
6456 typeDecl->subtypes->contentType;
6457 break;
6458 }
6459 case XML_SCHEMA_TYPE_RESTRICTION:{
6460 if (typeDecl->subtypes != NULL)
6461 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006462
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006463 if (typeDecl->base != NULL) {
6464 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00006465
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006466 baseType =
6467 xmlSchemaGetType(ctxt->schema, typeDecl->base,
6468 typeDecl->baseNs);
6469 if (baseType == NULL) {
6470 xmlSchemaPErr(ctxt, typeDecl->node,
6471 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00006472 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006473 name, typeDecl->base);
Daniel Veillard3646d642004-06-02 19:19:14 +00006474 } else if (baseType->contentType ==
6475 XML_SCHEMA_CONTENT_UNKNOWN) {
6476 /*
6477 * The base type might be not "type fixed" yet,
6478 * so do it now. */
6479 /*
6480 * TODO: Is a check for circular derivation already
6481 * done?
6482 */
6483 xmlSchemaTypeFixup(baseType, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006484 }
6485 typeDecl->baseType = baseType;
6486 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006487 if (typeDecl->subtypes == NULL)
William M. Bracke7091952004-05-11 15:09:58 +00006488 if (typeDecl->baseType != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006489 typeDecl->contentType =
6490 typeDecl->baseType->contentType;
William M. Bracke7091952004-05-11 15:09:58 +00006491 } else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006492 /* 1.1.1 */
6493 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006494 else if ((typeDecl->subtypes->subtypes == NULL) &&
6495 ((typeDecl->subtypes->type ==
6496 XML_SCHEMA_TYPE_ALL)
6497 || (typeDecl->subtypes->type ==
6498 XML_SCHEMA_TYPE_SEQUENCE)))
6499 /* 1.1.2 */
6500 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
6501 else if ((typeDecl->subtypes->type ==
6502 XML_SCHEMA_TYPE_CHOICE)
6503 && (typeDecl->subtypes->subtypes == NULL))
6504 /* 1.1.3 */
6505 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
6506 else {
6507 /* 1.2 and 2.X are applied at the other layer */
6508 typeDecl->contentType =
6509 XML_SCHEMA_CONTENT_ELEMENTS;
6510 }
6511 break;
6512 }
6513 case XML_SCHEMA_TYPE_EXTENSION:{
6514 xmlSchemaContentType explicitContentType;
6515 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00006516
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006517 if (typeDecl->base != NULL) {
6518 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00006519
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006520 baseType =
6521 xmlSchemaGetType(ctxt->schema, typeDecl->base,
6522 typeDecl->baseNs);
6523 if (baseType == NULL) {
6524 xmlSchemaPErr(ctxt, typeDecl->node,
6525 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00006526 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006527 name, typeDecl->base);
Daniel Veillard3646d642004-06-02 19:19:14 +00006528 } else if (baseType->contentType ==
6529 XML_SCHEMA_CONTENT_UNKNOWN) {
6530 /*
6531 * The base type might be not "type fixed" yet,
6532 * so do it now. */
6533 /*
6534 * TODO: Is a check for circular derivation already
6535 * done?
6536 */
6537 xmlSchemaTypeFixup(baseType, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006538 }
6539 typeDecl->baseType = baseType;
6540 }
6541 if (typeDecl->subtypes != NULL)
6542 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006543
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006544 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
6545 if (typeDecl->subtypes == NULL)
6546 /* 1.1.1 */
6547 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
6548 else if ((typeDecl->subtypes->subtypes == NULL) &&
6549 ((typeDecl->subtypes->type ==
6550 XML_SCHEMA_TYPE_ALL)
6551 || (typeDecl->subtypes->type ==
6552 XML_SCHEMA_TYPE_SEQUENCE)))
6553 /* 1.1.2 */
6554 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
6555 else if ((typeDecl->subtypes->type ==
6556 XML_SCHEMA_TYPE_CHOICE)
6557 && (typeDecl->subtypes->subtypes == NULL))
6558 /* 1.1.3 */
6559 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00006560
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006561 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
6562 typeDecl->baseNs);
6563 if (base == NULL) {
6564 xmlSchemaPErr(ctxt, typeDecl->node,
6565 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
6566 "Schemas: base type %s of type %s not found\n",
6567 typeDecl->base, name);
6568 return;
6569 }
Daniel Veillard2582a332004-04-18 19:49:46 +00006570 if (typeDecl->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006571 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillard2582a332004-04-18 19:49:46 +00006572 xmlSchemaPErr(ctxt, typeDecl->node,
6573 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
6574 "Schemas: extension type %s is recursive\n",
6575 name, NULL);
6576 return;
6577 }
6578 typeDecl->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006579 xmlSchemaTypeFixup(base, ctxt, NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +00006580 typeDecl->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006581 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
6582 /* 2.1 */
6583 typeDecl->contentType = base->contentType;
6584 } else if (base->contentType ==
6585 XML_SCHEMA_CONTENT_EMPTY) {
6586 /* 2.2 imbitable ! */
6587 typeDecl->contentType =
6588 XML_SCHEMA_CONTENT_ELEMENTS;
6589 } else {
6590 /* 2.3 imbitable pareil ! */
6591 typeDecl->contentType =
6592 XML_SCHEMA_CONTENT_ELEMENTS;
6593 }
6594 break;
6595 }
6596 case XML_SCHEMA_TYPE_COMPLEX:{
6597 if (typeDecl->subtypes == NULL) {
6598 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00006599
6600 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
6601 typeDecl->contentType =
6602 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006603 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00006604 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006605 typeDecl->contentType =
6606 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +00006607 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006608 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
6609 NULL);
6610 if (typeDecl->subtypes != NULL)
6611 typeDecl->contentType =
6612 typeDecl->subtypes->contentType;
6613 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006614 /* Evaluate the derivation method. */
6615 if ((typeDecl->subtypes != NULL) &&
6616 ((typeDecl->subtypes->type ==
6617 XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
6618 (typeDecl->subtypes->type ==
6619 XML_SCHEMA_TYPE_SIMPLE_CONTENT)) &&
6620 (typeDecl->subtypes->subtypes != NULL)) {
6621 if (typeDecl->subtypes->subtypes->type ==
6622 XML_SCHEMA_TYPE_EXTENSION) {
6623 typeDecl->flags |=
6624 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
6625 } else if (typeDecl->subtypes->subtypes->type ==
6626 XML_SCHEMA_TYPE_RESTRICTION) {
6627 typeDecl->flags |=
6628 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006629 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006630 }
6631 }
6632 xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006633 break;
6634 }
6635 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
6636 if (typeDecl->subtypes == NULL) {
6637 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00006638 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
6639 typeDecl->contentType =
6640 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006641 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00006642 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006643 typeDecl->contentType =
6644 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +00006645 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006646 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
6647 NULL);
6648 if (typeDecl->subtypes != NULL)
6649 typeDecl->contentType =
6650 typeDecl->subtypes->contentType;
6651 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006652 /*
6653 * Removed due to implementation of the build of attribute uses.
6654 */
6655 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00006656 if (typeDecl->attributes == NULL)
6657 typeDecl->attributes =
6658 typeDecl->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +00006659 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006660 }
6661 break;
6662 }
6663 case XML_SCHEMA_TYPE_SEQUENCE:
6664 case XML_SCHEMA_TYPE_GROUP:
6665 case XML_SCHEMA_TYPE_ALL:
6666 case XML_SCHEMA_TYPE_CHOICE:
6667 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
6668 break;
Daniel Veillard3646d642004-06-02 19:19:14 +00006669 case XML_SCHEMA_TYPE_LIST:
6670 xmlSchemaParseListRefFixup(typeDecl, ctxt);
6671 /* no break on purpose */
6672 case XML_SCHEMA_TYPE_UNION:
6673 if (typeDecl->type == XML_SCHEMA_TYPE_UNION)
6674 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
6675 /* no break on purpose */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006676 case XML_SCHEMA_TYPE_BASIC:
6677 case XML_SCHEMA_TYPE_ANY:
6678 case XML_SCHEMA_TYPE_FACET:
6679 case XML_SCHEMA_TYPE_SIMPLE:
6680 case XML_SCHEMA_TYPE_UR:
6681 case XML_SCHEMA_TYPE_ELEMENT:
6682 case XML_SCHEMA_TYPE_ATTRIBUTE:
6683 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +00006684 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006685 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006686 case XML_SCHEMA_FACET_MININCLUSIVE:
6687 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6688 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6689 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
6690 case XML_SCHEMA_FACET_TOTALDIGITS:
6691 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6692 case XML_SCHEMA_FACET_PATTERN:
6693 case XML_SCHEMA_FACET_ENUMERATION:
6694 case XML_SCHEMA_FACET_WHITESPACE:
6695 case XML_SCHEMA_FACET_LENGTH:
6696 case XML_SCHEMA_FACET_MAXLENGTH:
6697 case XML_SCHEMA_FACET_MINLENGTH:
6698 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006699 if (typeDecl->subtypes != NULL)
6700 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006701 break;
6702 }
6703 }
Daniel Veillard8651f532002-04-17 09:06:27 +00006704#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006705 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006706 xmlGenericError(xmlGenericErrorContext,
6707 "Type of %s : %s:%d :", name,
6708 typeDecl->node->doc->URL,
6709 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006710 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006711 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006712 }
Daniel Veillard8651f532002-04-17 09:06:27 +00006713 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006714 case XML_SCHEMA_CONTENT_SIMPLE:
6715 xmlGenericError(xmlGenericErrorContext, "simple\n");
6716 break;
6717 case XML_SCHEMA_CONTENT_ELEMENTS:
6718 xmlGenericError(xmlGenericErrorContext, "elements\n");
6719 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006720 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006721 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
6722 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006723 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006724 xmlGenericError(xmlGenericErrorContext, "empty\n");
6725 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006726 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006727 xmlGenericError(xmlGenericErrorContext, "mixed\n");
6728 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006729 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006730 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
6731 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006732 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006733 xmlGenericError(xmlGenericErrorContext, "basic\n");
6734 break;
6735 default:
6736 xmlGenericError(xmlGenericErrorContext,
6737 "not registered !!!\n");
6738 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006739 }
6740#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00006741}
6742
6743/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006744 * xmlSchemaCheckFacet:
6745 * @facet: the facet
6746 * @typeDecl: the schema type definition
6747 * @ctxt: the schema parser context or NULL
6748 * @name: name of the type
6749 *
6750 * Checks the default values types, especially for facets
6751 *
6752 * Returns 0 if okay or -1 in cae of error
6753 */
6754int
6755xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006756 xmlSchemaTypePtr typeDecl,
6757 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006758{
6759 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
6760 int ret = 0;
6761
6762 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006763 nonNegativeIntegerType =
6764 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
6765 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006766 }
6767 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006768 case XML_SCHEMA_FACET_MININCLUSIVE:
6769 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6770 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6771 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
6772 /*
6773 * Okay we need to validate the value
6774 * at that point.
6775 */
6776 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006777
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006778 vctxt = xmlSchemaNewValidCtxt(NULL);
6779 if (vctxt == NULL)
6780 break;
6781 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
6782 facet->value);
6783 facet->val = vctxt->value;
6784 vctxt->value = NULL;
6785 if (facet->val == NULL) {
6786 /* error code */
6787 if (ctxt != NULL) {
6788 xmlSchemaPErr(ctxt, facet->node,
6789 XML_SCHEMAP_INVALID_FACET,
6790 "Schemas: type %s facet value %s invalid\n",
6791 name, facet->value);
6792 }
6793 ret = -1;
6794 }
6795 xmlSchemaFreeValidCtxt(vctxt);
6796 break;
6797 }
6798 case XML_SCHEMA_FACET_ENUMERATION:{
6799 /*
6800 * Okay we need to validate the value
6801 * at that point.
6802 */
6803 xmlSchemaValidCtxtPtr vctxt;
6804 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006805
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006806 vctxt = xmlSchemaNewValidCtxt(NULL);
6807 if (vctxt == NULL)
6808 break;
6809 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
6810 facet->value);
6811 if (tmp != 0) {
6812 if (ctxt != NULL) {
6813 xmlSchemaPErr(ctxt, facet->node,
6814 XML_SCHEMAP_INVALID_ENUM,
6815 "Schemas: type %s enumeration value %s invalid\n",
6816 name, facet->value);
6817 }
6818 ret = -1;
6819 }
6820 xmlSchemaFreeValidCtxt(vctxt);
6821 break;
6822 }
6823 case XML_SCHEMA_FACET_PATTERN:
6824 facet->regexp = xmlRegexpCompile(facet->value);
6825 if (facet->regexp == NULL) {
6826 xmlSchemaPErr(ctxt, typeDecl->node,
6827 XML_SCHEMAP_REGEXP_INVALID,
6828 "Schemas: type %s facet regexp %s invalid\n",
6829 name, facet->value);
6830 ret = -1;
6831 }
6832 break;
6833 case XML_SCHEMA_FACET_TOTALDIGITS:
6834 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6835 case XML_SCHEMA_FACET_LENGTH:
6836 case XML_SCHEMA_FACET_MAXLENGTH:
6837 case XML_SCHEMA_FACET_MINLENGTH:{
6838 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006839
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006840 tmp =
6841 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
6842 facet->value,
6843 &facet->val);
6844 if (tmp != 0) {
6845 /* error code */
6846 if (ctxt != NULL) {
6847 xmlSchemaPErr(ctxt, facet->node,
6848 XML_SCHEMAP_INVALID_FACET_VALUE,
6849 "Schemas: type %s facet value %s invalid\n",
6850 name, facet->value);
6851 }
6852 ret = -1;
6853 }
6854 break;
6855 }
6856 case XML_SCHEMA_FACET_WHITESPACE:{
6857 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
6858 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
6859 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
6860 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
6861 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
6862 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
6863 } else {
6864 if (ctxt != NULL) {
6865 xmlSchemaPErr(ctxt, facet->node,
6866 XML_SCHEMAP_INVALID_WHITE_SPACE,
6867 "Schemas: type %s whiteSpace value %s invalid\n",
6868 name, facet->value);
6869 }
6870 ret = -1;
6871 }
6872 }
6873 default:
6874 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006875 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006876 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006877}
6878
6879/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006880 * xmlSchemaCheckDefaults:
6881 * @typeDecl: the schema type definition
6882 * @ctxt: the schema parser context
6883 *
6884 * Checks the default values types, especially for facets
6885 */
6886static void
6887xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006888 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00006889{
Daniel Veillard4255d502002-04-16 15:50:10 +00006890 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006891 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006892 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006893 if (typeDecl->facets != NULL) {
6894 xmlSchemaFacetPtr facet = typeDecl->facets;
6895
6896 while (facet != NULL) {
6897 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
6898 facet = facet->next;
6899 }
6900 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006901 }
6902}
6903
6904/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00006905 * xmlSchemaAttrGrpFixup:
6906 * @attrgrpDecl: the schema attribute definition
6907 * @ctxt: the schema parser context
6908 * @name: the attribute name
6909 *
6910 * Fixes finish doing the computations on the attributes definitions
6911 */
6912static void
Daniel Veillard3646d642004-06-02 19:19:14 +00006913xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006914 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00006915{
6916 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00006917 name = attrgrp->name;
6918 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006919 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00006920 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006921 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006922
Daniel Veillard3646d642004-06-02 19:19:14 +00006923 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref, attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006924 if (ref == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006925 xmlSchemaPErr(ctxt, attrgrp->node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006926 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
6927 "Schemas: attribute group %s reference %s not found\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00006928 name, attrgrp->ref);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006929 return;
6930 }
6931 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00006932 attrgrp->attributes = ref->attributes;
6933 attrgrp->attributeWildcard = ref->attributeWildcard;
6934 }
6935 /*
6936 * Removed, since a global attribute group does not need to hold any
6937 * attributes or wildcard
6938 */
6939 /*
6940 else {
6941 xmlSchemaPErr(ctxt, attrgrp->node, XML_SCHEMAP_NOATTR_NOREF,
6942 "Schemas: attribute group %s has no attributes nor reference\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006943 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00006944 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006945 */
Daniel Veillard13e04c62002-04-23 17:51:29 +00006946}
6947
6948/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006949 * xmlSchemaAttrFixup:
6950 * @attrDecl: the schema attribute definition
6951 * @ctxt: the schema parser context
6952 * @name: the attribute name
6953 *
6954 * Fixes finish doing the computations on the attributes definitions
6955 */
6956static void
6957xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006958 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00006959{
6960 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006961 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006962 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006963 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006964 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006965 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006966
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006967 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
6968 attrDecl->typeNs);
6969 if (type == NULL) {
6970 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
6971 "Schemas: attribute %s type %s not found\n",
6972 name, attrDecl->typeName);
6973 }
6974 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006975 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006976 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00006977
Daniel Veillard3646d642004-06-02 19:19:14 +00006978 ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006979 if (ref == NULL) {
6980 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
6981 "Schemas: attribute %s reference %s not found\n",
6982 name, attrDecl->ref);
6983 return;
6984 }
6985 xmlSchemaAttrFixup(ref, ctxt, NULL);
6986 attrDecl->subtypes = ref->subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +00006987 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006988 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
6989 "Schemas: attribute %s has no type nor reference\n",
6990 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006991 }
6992}
6993
6994/**
6995 * xmlSchemaParse:
6996 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00006997 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00006998 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00006999 * XML Shema struture which can be used to validate instances.
7000 * *WARNING* this interface is highly subject to change
7001 *
7002 * Returns the internal XML Schema structure built from the resource or
7003 * NULL in case of error
7004 */
7005xmlSchemaPtr
7006xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
7007{
7008 xmlSchemaPtr ret = NULL;
7009 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007010 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007011 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00007012 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007013
7014 xmlSchemaInitTypes();
7015
Daniel Veillard6045c902002-10-09 21:13:59 +00007016 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00007017 return (NULL);
7018
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007019 nberrors = ctxt->nberrors;
7020 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007021 ctxt->counter = 0;
7022 ctxt->container = NULL;
7023
7024 /*
7025 * First step is to parse the input document into an DOM/Infoset
7026 */
Daniel Veillard6045c902002-10-09 21:13:59 +00007027 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007028 doc = xmlReadFile((const char *) ctxt->URL, NULL,
7029 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007030 if (doc == NULL) {
7031 xmlSchemaPErr(ctxt, NULL,
7032 XML_SCHEMAP_FAILED_LOAD,
7033 "xmlSchemaParse: could not load %s\n",
7034 ctxt->URL, NULL);
7035 return (NULL);
7036 }
Daniel Veillard6045c902002-10-09 21:13:59 +00007037 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007038 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
7039 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007040 if (doc == NULL) {
7041 xmlSchemaPErr(ctxt, NULL,
7042 XML_SCHEMAP_FAILED_PARSE,
7043 "xmlSchemaParse: could not parse\n",
7044 NULL, NULL);
7045 return (NULL);
7046 }
7047 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00007048 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00007049 } else if (ctxt->doc != NULL) {
7050 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00007051 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00007052 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007053 xmlSchemaPErr(ctxt, NULL,
7054 XML_SCHEMAP_NOTHING_TO_PARSE,
7055 "xmlSchemaParse: could not parse\n",
7056 NULL, NULL);
7057 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007058 }
7059
7060 /*
7061 * Then extract the root and Schema parse it
7062 */
7063 root = xmlDocGetRootElement(doc);
7064 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007065 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
7066 XML_SCHEMAP_NOROOT,
7067 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00007068 if (!preserve) {
7069 xmlFreeDoc(doc);
7070 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007071 return (NULL);
7072 }
7073
7074 /*
7075 * Remove all the blank text nodes
7076 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007077 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00007078
7079 /*
7080 * Then do the parsing for good
7081 */
7082 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00007083 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00007084 if (!preserve) {
7085 xmlFreeDoc(doc);
7086 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007087 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00007088 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007089 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00007090 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00007091
7092 /*
7093 * Then fix all the references.
7094 */
7095 ctxt->schema = ret;
7096 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007097 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00007098
7099 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00007100 * Then fixup all attributes declarations
7101 */
7102 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
7103
7104 /*
7105 * Then fixup all attributes group declarations
7106 */
7107 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
7108 ctxt);
7109
7110 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00007111 * Then fixup all types properties
7112 */
7113 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
7114
7115 /*
7116 * Then build the content model for all elements
7117 */
7118 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007119 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00007120
7121 /*
7122 * Then check the defaults part of the type like facets values
7123 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007124 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
7125 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00007126
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007127 if (ctxt->nberrors != 0) {
7128 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007129 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007130 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007131 return (ret);
7132}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007133
Daniel Veillard4255d502002-04-16 15:50:10 +00007134/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00007135 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00007136 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00007137 * @err: the error callback
7138 * @warn: the warning callback
7139 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00007140 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00007141 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00007142 */
7143void
7144xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007145 xmlSchemaValidityErrorFunc err,
7146 xmlSchemaValidityWarningFunc warn, void *ctx)
7147{
Daniel Veillard4255d502002-04-16 15:50:10 +00007148 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007149 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007150 ctxt->error = err;
7151 ctxt->warning = warn;
7152 ctxt->userData = ctx;
7153}
7154
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007155/**
7156 * xmlSchemaFacetTypeToString:
7157 * @type: the facet type
7158 *
7159 * Convert the xmlSchemaTypeType to a char string.
7160 *
7161 * Returns the char string representation of the facet type if the
7162 * type is a facet and an "Internal Error" string otherwise.
7163 */
7164static const char *
7165xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
7166{
7167 switch (type) {
7168 case XML_SCHEMA_FACET_PATTERN:
7169 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007170 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007171 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007172 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007173 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007174 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007175 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007176 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007177 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007178 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007179 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007180 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007181 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007182 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007183 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007184 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007185 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007186 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007187 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007188 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007189 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007190 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007191 return ("fractionDigits");
7192 default:
7193 break;
7194 }
7195 return ("Internal Error");
7196}
7197
7198/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00007199 * xmlSchemaValidateFacetsInternal:
7200 * @ctxt: a schema validation context
7201 * @base: the base type
7202 * @facets: the list of facets to check
7203 * @value: the lexical repr of the value to validate
7204 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +00007205 * @fireErrors: if 0, only internal errors will be fired;
7206 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00007207 *
7208 * Check a value against all facet conditions
7209 *
7210 * Returns 0 if the element is schemas valid, a positive error code
7211 * number otherwise and -1 in case of internal or API error.
7212 */
7213static int
7214xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
7215 xmlSchemaTypePtr base,
William M. Bracke7091952004-05-11 15:09:58 +00007216 xmlSchemaFacetPtr facets,
7217 const xmlChar * value, int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00007218{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007219 int ret = 0;
7220 int tmp = 0;
7221 xmlSchemaTypeType type;
7222 xmlSchemaFacetPtr facet = facets;
7223
7224 while (facet != NULL) {
7225 type = facet->type;
7226 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007227 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007228
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007229 while (facet != NULL) {
7230 tmp =
7231 xmlSchemaValidateFacet(base, facet, value,
7232 ctxt->value);
7233 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007234 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007235 }
7236 facet = facet->next;
7237 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007238 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007239 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007240
7241 if (tmp != 0) {
7242 ret = tmp;
Daniel Veillard377e1a92004-04-16 16:30:05 +00007243 if (fireErrors)
William M. Bracke7091952004-05-11 15:09:58 +00007244 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET,
7245 "Failed to validate type with facet %s\n",
7246 (const xmlChar *) xmlSchemaFacetTypeToString(type),
7247 NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007248 }
7249 if (facet != NULL)
7250 facet = facet->next;
7251 }
7252 return (ret);
7253}
7254
William M. Brack87640d52004-04-17 14:58:15 +00007255/**
7256 * xmlSchemaValidateFacets:
7257 * @ctxt: a schema validation context
7258 * @base: the base type
7259 * @facets: the list of facets to check
7260 * @value: the lexical repr of the value to validate
7261 * @val: the precomputed value
7262 *
7263 * Check a value against all facet conditions
7264 *
7265 * Returns 0 if the element is schemas valid, a positive error code
7266 * number otherwise and -1 in case of internal or API error.
7267 */
7268static int
7269xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
7270 xmlSchemaTypePtr base,
7271 xmlSchemaFacetPtr facets, const xmlChar * value)
7272{
7273 return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
7274}
7275
Daniel Veillard4255d502002-04-16 15:50:10 +00007276/************************************************************************
7277 * *
7278 * Simple type validation *
7279 * *
7280 ************************************************************************/
7281
7282/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00007283 * xmlSchemaValidateSimpleValueUnion:
7284 * @ctxt: a schema validation context
7285 * @type: the type declaration
7286 * @value: the value to validate
7287 *
7288 * Validates a value against a union.
7289 *
7290 * Returns 0 if the value is valid, a positive error code
7291 * number otherwise and -1 in case of internal or API error.
7292 */
7293static int
7294xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
7295 xmlSchemaTypePtr type, const xmlChar * value)
7296{
7297 int ret = 0;
7298 const xmlChar *cur, *end, *prefix, *ncName;
7299 xmlChar *tmp;
7300 xmlSchemaTypePtr subtype;
7301 xmlNsPtr ns;
7302 int len;
7303
7304
7305 /* Process referenced memberTypes. */
7306 cur = type->ref;
7307 do {
7308 while (IS_BLANK_CH(*cur))
7309 cur++;
7310 end = cur;
7311 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7312 end++;
7313 if (end == cur)
7314 break;
7315 tmp = xmlStrndup(cur, end - cur);
7316 ncName = xmlSplitQName3(tmp, &len);
7317 if (ncName != NULL) {
7318 prefix = xmlStrndup(tmp, len);
7319 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
7320 } else {
7321 prefix = NULL;
7322 ncName = tmp;
7323 }
William M. Bracke7091952004-05-11 15:09:58 +00007324 /* We won't do additional checks here,
7325 * since they have been performed during parsing. */
Daniel Veillard377e1a92004-04-16 16:30:05 +00007326 ns = xmlSearchNs(type->node->doc, type->node, prefix);
7327 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
7328 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
7329 if (tmp != NULL)
7330 xmlFree(tmp);
7331 if (prefix != NULL)
William M. Brack87640d52004-04-17 14:58:15 +00007332 xmlFree((void *)prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007333 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
7334 if ((ret == 0) || (ret == -1)) {
7335 return (ret);
7336 }
7337 cur = end;
7338 } while (*cur != 0);
7339
7340 if (type->subtypes != NULL) {
7341 subtype = type->subtypes;
7342 do {
7343 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
7344 if ((ret == 0) || (ret == -1)) {
7345 return (ret);
7346 }
7347 subtype = subtype->next;
7348 } while (subtype != NULL);
7349 }
7350 return (ret);
7351}
7352
7353/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007354 * xmlSchemaValidateSimpleValue:
7355 * @ctxt: a schema validation context
7356 * @type: the type declaration
7357 * @value: the value to validate
7358 *
7359 * Validate a value against a simple type
7360 *
7361 * Returns 0 if the value is valid, a positive error code
7362 * number otherwise and -1 in case of internal or API error.
7363 */
7364static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007365xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007366 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007367{
Daniel Veillard377e1a92004-04-16 16:30:05 +00007368 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
7369}
7370
7371/**
7372 * xmlSchemaValidateSimpleValue:
7373 * @ctxt: a schema validation context
7374 * @type: the type declaration
7375 * @value: the value to validate
William M. Bracke7091952004-05-11 15:09:58 +00007376 * @fireErrors: if 0, only internal errors will be fired;
7377 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00007378 *
7379 * Validate a value against a simple type
7380 *
7381 * Returns 0 if the value is valid, a positive error code
7382 * number otherwise and -1 in case of internal or API error.
7383 */
7384static int
7385xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
William M. Bracke7091952004-05-11 15:09:58 +00007386 xmlSchemaTypePtr type,
7387 const xmlChar * value,
7388 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00007389{
Daniel Veillard4255d502002-04-16 15:50:10 +00007390 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007391
Daniel Veillard4255d502002-04-16 15:50:10 +00007392 /*
7393 * First normalize the value accordingly to Schema Datatype
7394 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
William M. Bracke7091952004-05-11 15:09:58 +00007395 *
Daniel Veillard4255d502002-04-16 15:50:10 +00007396 * Then check the normalized value against the lexical space of the
7397 * type.
7398 */
7399 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007400 if (ctxt->value != NULL) {
7401 xmlSchemaFreeValue(ctxt->value);
7402 ctxt->value = NULL;
7403 }
7404 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
7405 ctxt->cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007406 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00007407 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
7408 "Failed to validate basic type %s\n",
7409 type->name, NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007410 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007411 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007412 xmlSchemaTypePtr base;
7413 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00007414
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007415 base = type->baseType;
7416 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00007417 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
7418 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007419 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007420 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007421 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007422
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007423 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00007424 * Do not validate facets or attributes when working on
7425 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007426 */
7427 if (ctxt->schema != NULL) {
7428 if (ret == 0) {
7429 facet = type->facets;
William M. Bracke7091952004-05-11 15:09:58 +00007430 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet,
7431 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007432 }
7433 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007434 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007435 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00007436
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007437 base = type->subtypes;
7438 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00007439 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
7440 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007441 } else {
7442 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00007443 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007444 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007445 const xmlChar *cur, *end;
7446 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007447 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00007448
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007449 base = type->subtypes;
7450 if (base == NULL) {
7451 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
7452 "Internal: List type %s has no base type\n",
7453 type->name, NULL);
7454 return (-1);
7455 }
7456 cur = value;
7457 do {
William M. Brack76e95df2003-10-18 16:20:14 +00007458 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007459 cur++;
7460 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00007461 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007462 end++;
7463 if (end == cur)
7464 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007465 tmp = xmlStrndup(cur, end - cur);
William M. Bracke7091952004-05-11 15:09:58 +00007466 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base,
7467 tmp, fireErrors);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007468 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007469 if (ret2 != 0)
7470 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007471 cur = end;
7472 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007473 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
7474 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
7475 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00007476 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
7477 "Failed to validate type %s\n", type->name, NULL);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007478 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007479 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007480 TODO
7481 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007482 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007483}
7484
7485/************************************************************************
7486 * *
7487 * DOM Validation code *
7488 * *
7489 ************************************************************************/
7490
7491static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007492 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007493static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007494 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +00007495 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007496static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007497 xmlNodePtr elem,
7498 xmlSchemaElementPtr elemDecl,
7499 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007500
Daniel Veillard3646d642004-06-02 19:19:14 +00007501
7502/**
7503 * xmlSchemaFreeAttrStates:
7504 * @state: a list of attribute states
7505 *
7506 * Free the given list of attribute states
7507 *
7508 */
7509static void
7510xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
7511{
7512 xmlSchemaAttrStatePtr tmp;
7513 while (state != NULL) {
7514 tmp = state;
7515 state = state->next;
7516 xmlFree(tmp);
7517 }
7518}
7519
Daniel Veillard4255d502002-04-16 15:50:10 +00007520/**
7521 * xmlSchemaRegisterAttributes:
7522 * @ctxt: a schema validation context
7523 * @attrs: a list of attributes
7524 *
7525 * Register the list of attributes as the set to be validated on that element
7526 *
7527 * Returns -1 in case of error, 0 otherwise
7528 */
7529static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007530xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
7531{
Daniel Veillard3646d642004-06-02 19:19:14 +00007532 xmlSchemaAttrStatePtr tmp;
7533
7534 ctxt->attr = NULL;
7535 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007536 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007537 if ((attrs->ns != NULL) &&
7538 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
7539 attrs = attrs->next;
7540 continue;
7541 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007542 tmp = (xmlSchemaAttrStatePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00007543 xmlMalloc(sizeof(xmlSchemaAttrState));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007544 if (tmp == NULL) {
7545 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007546 return (-1);
7547 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007548 tmp->attr = attrs;
7549 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
7550 tmp->next = NULL;
7551 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007552 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00007553 else
7554 ctxt->attrTop->next = tmp;
7555 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007556 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007557 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007558 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007559}
7560
7561/**
7562 * xmlSchemaCheckAttributes:
7563 * @ctxt: a schema validation context
7564 * @node: the node carrying it.
7565 *
7566 * Check that the registered set of attributes on the current node
7567 * has been properly validated.
7568 *
7569 * Returns 0 if validity constraints are met, 1 otherwise.
7570 */
7571static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007572xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7573{
Daniel Veillard4255d502002-04-16 15:50:10 +00007574 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00007575 xmlSchemaAttrStatePtr cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00007576
Daniel Veillard3646d642004-06-02 19:19:14 +00007577 cur = ctxt->attr;
7578 while ((cur != NULL) && (cur != ctxt->attrTop->next)) {
7579 if (cur->state != XML_SCHEMAS_ATTR_CHECKED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007580 ret = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00007581 if (cur->state == XML_SCHEMAS_ATTR_UNKNOWN)
William M. Bracke7091952004-05-11 15:09:58 +00007582 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
7583 "Attribute %s on %s is unknown\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00007584 cur->attr->name, node->name);
7585 else if (cur->state == XML_SCHEMAS_ATTR_PROHIBITED)
7586 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
7587 "Attribute %s on %s is prohibited\n",
7588 cur->attr->name, node->name);
7589 else if (cur->state == XML_SCHEMAS_ATTR_INVALID_VALUE)
7590 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRINVALID,
7591 "Attribute %s on %s does not match type\n",
7592 cur->attr->name, node->name);
7593 else if (cur->state == XML_SCHEMAS_ATTR_MISSING) {
7594 if (cur->decl->ref != NULL)
7595 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
7596 "Attribute %s on %s is required but missing\n",
7597 cur->decl->ref, node->name);
7598 else
7599 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
7600 "Attribute %s on %s is required but missing\n",
7601 cur->decl->name, node->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007602 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007603 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007604 cur = cur->next;
7605 }
7606
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007607 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007608}
7609
William M. Brack29aa7722004-05-12 00:27:56 +00007610#if 0 /* Not currently used - remove if ever needed */
Daniel Veillard4255d502002-04-16 15:50:10 +00007611/**
7612 * xmlSchemaValidateSimpleContent:
7613 * @ctxt: a schema validation context
7614 * @elem: an element
7615 * @type: the type declaration
7616 *
7617 * Validate the content of an element expected to be a simple type
7618 *
7619 * Returns 0 if the element is schemas valid, a positive error code
7620 * number otherwise and -1 in case of internal or API error.
7621 */
7622static int
7623xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007624 xmlNodePtr node ATTRIBUTE_UNUSED)
7625{
Daniel Veillard4255d502002-04-16 15:50:10 +00007626 xmlNodePtr child;
7627 xmlSchemaTypePtr type, base;
7628 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007629 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007630
7631 child = ctxt->node;
7632 type = ctxt->type;
7633
7634 /*
7635 * Validation Rule: Element Locally Valid (Type): 3.1.3
7636 */
7637 value = xmlNodeGetContent(child);
7638 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
7639 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007640 case XML_SCHEMA_TYPE_RESTRICTION:{
7641 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00007642
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007643 base = type->baseType;
7644 if (base != NULL) {
7645 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
7646 } else {
7647 TODO}
7648 if (ret == 0) {
7649 facet = type->facets;
7650 ret =
7651 xmlSchemaValidateFacets(ctxt, base, facet, value);
7652 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007653 /*
7654 * This should attempt to validate the attributes even
7655 * when validation of the value failed.
7656 */
7657 /*
7658 if (type->attributes != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00007659 ret = xmlSchemaValidateAttributes(ctxt, node,
7660 type->attributes);
7661 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007662 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007663 break;
7664 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007665 case XML_SCHEMA_TYPE_EXTENSION:{
7666 TODO
7667 break;
7668 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007669 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007670 TODO
7671 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007672 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007673 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00007674
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007675 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007676}
William M. Brack29aa7722004-05-12 00:27:56 +00007677#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00007678
7679/**
7680 * xmlSchemaValidateCheckNodeList
7681 * @nodelist: the list of nodes
7682 *
7683 * Check the node list is only made of text nodes and entities pointing
7684 * to text nodes
7685 *
7686 * Returns 1 if true, 0 if false and -1 in case of error
7687 */
7688static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007689xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
7690{
Daniel Veillard4255d502002-04-16 15:50:10 +00007691 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007692 if (nodelist->type == XML_ENTITY_REF_NODE) {
7693 TODO /* implement recursion in the entity content */
7694 }
7695 if ((nodelist->type != XML_TEXT_NODE) &&
7696 (nodelist->type != XML_COMMENT_NODE) &&
7697 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +00007698 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007699 return (0);
7700 }
7701 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007702 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007703 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007704}
7705
7706/**
7707 * xmlSchemaSkipIgnored:
7708 * @ctxt: a schema validation context
7709 * @type: the current type context
7710 * @node: the top node.
7711 *
7712 * Skip ignorable nodes in that context
7713 *
7714 * Returns the new sibling
7715 * number otherwise and -1 in case of internal or API error.
7716 */
7717static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00007718xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007719 xmlSchemaTypePtr type, xmlNodePtr node)
7720{
Daniel Veillard4255d502002-04-16 15:50:10 +00007721 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007722
Daniel Veillard4255d502002-04-16 15:50:10 +00007723 /*
7724 * TODO complete and handle entities
7725 */
7726 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007727 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00007728 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007729 ((node->type == XML_COMMENT_NODE) ||
7730 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
7731 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
7732 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
7733 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007734 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007735 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007736}
7737
7738/**
7739 * xmlSchemaValidateCallback:
7740 * @ctxt: a schema validation context
7741 * @name: the name of the element detected (might be NULL)
7742 * @type: the type
7743 *
7744 * A transition has been made in the automata associated to an element
7745 * content model
7746 */
7747static void
7748xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007749 const xmlChar * name ATTRIBUTE_UNUSED,
7750 xmlSchemaTypePtr type, xmlNodePtr node)
7751{
Daniel Veillard4255d502002-04-16 15:50:10 +00007752 xmlSchemaTypePtr oldtype = ctxt->type;
7753 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007754
Daniel Veillard4255d502002-04-16 15:50:10 +00007755#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00007756 xmlGenericError(xmlGenericErrorContext,
7757 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007758 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00007759#endif
7760 ctxt->type = type;
7761 ctxt->node = node;
7762 xmlSchemaValidateContent(ctxt, node);
7763 ctxt->type = oldtype;
7764 ctxt->node = oldnode;
7765}
7766
7767
7768#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007769
Daniel Veillard4255d502002-04-16 15:50:10 +00007770/**
7771 * xmlSchemaValidateSimpleRestrictionType:
7772 * @ctxt: a schema validation context
7773 * @node: the top node.
7774 *
7775 * Validate the content of a restriction type.
7776 *
7777 * Returns 0 if the element is schemas valid, a positive error code
7778 * number otherwise and -1 in case of internal or API error.
7779 */
7780static int
7781xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
7782 xmlNodePtr node)
7783{
7784 xmlNodePtr child;
7785 xmlSchemaTypePtr type;
7786 int ret;
7787
7788 child = ctxt->node;
7789 type = ctxt->type;
7790
7791 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00007792 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7793 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
7794 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007795 return (-1);
7796 }
7797 /*
7798 * Only text and text based entities references shall be found there
7799 */
7800 ret = xmlSchemaValidateCheckNodeList(child);
7801 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007802 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7803 "Internal error: xmlSchemaValidateSimpleType %s content\n",
7804 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007805 return (-1);
7806 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007807 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
7808 "Element %s content is not a simple type\n",
7809 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007810 return (-1);
7811 }
7812 ctxt->type = type->subtypes;
7813 xmlSchemaValidateContent(ctxt, node);
7814 ctxt->type = type;
7815 return (ret);
7816}
7817#endif
7818
7819/**
7820 * xmlSchemaValidateSimpleType:
7821 * @ctxt: a schema validation context
7822 * @node: the top node.
7823 *
7824 * Validate the content of an simple type.
7825 *
7826 * Returns 0 if the element is schemas valid, a positive error code
7827 * number otherwise and -1 in case of internal or API error.
7828 */
7829static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007830xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7831{
Daniel Veillard4255d502002-04-16 15:50:10 +00007832 xmlNodePtr child;
William M. Bracke7091952004-05-11 15:09:58 +00007833 xmlSchemaTypePtr type, base, variety;
Daniel Veillard4255d502002-04-16 15:50:10 +00007834 xmlAttrPtr attr;
7835 int ret;
William M. Bracke7091952004-05-11 15:09:58 +00007836 xmlChar *value;
7837
Daniel Veillard4255d502002-04-16 15:50:10 +00007838
7839 child = ctxt->node;
7840 type = ctxt->type;
7841
7842 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00007843 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7844 "Internal error: xmlSchemaValidateSimpleType %s\n",
7845 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007846 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007847 }
7848 /*
7849 * Only text and text based entities references shall be found there
7850 */
7851 ret = xmlSchemaValidateCheckNodeList(child);
7852 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007853 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7854 "Internal error: xmlSchemaValidateSimpleType %s content\n",
7855 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007856 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007857 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007858 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
7859 "Element %s content is not a simple type\n",
7860 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007861 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007862 }
7863 /*
7864 * Validation Rule: Element Locally Valid (Type): 3.1.1
William M. Bracke7091952004-05-11 15:09:58 +00007865 */
7866
Daniel Veillard4255d502002-04-16 15:50:10 +00007867 attr = node->properties;
7868 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007869 if ((attr->ns == NULL) ||
7870 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
7871 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
7872 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
7873 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
7874 (!xmlStrEqual
7875 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
William M. Bracke7091952004-05-11 15:09:58 +00007876 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
7877 "Element %s: attribute %s should not be present\n",
7878 node->name, attr->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007879 return (ctxt->err);
7880 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007881 }
William M. Bracke7091952004-05-11 15:09:58 +00007882 /* TODO:
7883 * If {variety} is ·atomic· then the {variety} of {base type definition}
7884 * must be ·atomic·.
7885 * If {variety} is ·list· then the {variety} of {item type definition}
7886 * must be either ·atomic· or ·union·.
7887 * If {variety} is ·union· then {member type definitions} must be a list
7888 * of datatype definitions.
7889 */
7890 if (type->subtypes == NULL) {
7891 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7892 "Internal error: xmlSchemaValidateSimpleType; "
7893 "simple type %s does not define a variety\n",
7894 node->name, NULL);
7895 return (ctxt->err);
7896 }
7897 /* Varieties: Restriction or List or Union. */
7898 variety = type->subtypes;
7899 ctxt->type = variety;
7900 value = xmlNodeGetContent(child);
7901 switch (variety->type) {
7902 case XML_SCHEMA_TYPE_RESTRICTION:{
7903 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00007904
William M. Bracke7091952004-05-11 15:09:58 +00007905 base = variety->baseType;
7906 if (base != NULL) {
7907 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
7908 } else {
7909 TODO}
7910 if (ret == 0) {
7911 facet = variety->facets;
7912 ret =
7913 xmlSchemaValidateFacets(ctxt, base, facet, value);
7914 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007915 /* Removed due to changes of attribute validation:
William M. Bracke7091952004-05-11 15:09:58 +00007916 if ((ret == 0) && (variety->attributes != NULL)) {
7917 ret = xmlSchemaValidateAttributes(ctxt, node,
7918 variety->attributes);
7919 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007920 */
William M. Bracke7091952004-05-11 15:09:58 +00007921 break;
7922 }
7923 case XML_SCHEMA_TYPE_LIST:
7924 case XML_SCHEMA_TYPE_UNION: {
7925 ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
7926 break;
7927 }
7928 default:{
7929 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7930 "Internal error: xmlSchemaValidateSimpleType; "
7931 "simple type %s defines unknown content: %s\n",
7932 variety->name, NULL);
7933 ret = ctxt->err;
7934 }
7935 }
7936 if (value != NULL)
7937 xmlFree(value);
7938
7939 /* This was removed, since a simple content is not a content of a
7940 * simple type, but of a complex type.
7941 * ret = xmlSchemaValidateSimpleContent(ctxt, node);
7942 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007943 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007944 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007945}
7946
7947/**
7948 * xmlSchemaValidateElementType:
7949 * @ctxt: a schema validation context
7950 * @node: the top node.
7951 *
7952 * Validate the content of an element type.
7953 * Validation Rule: Element Locally Valid (Complex Type)
7954 *
7955 * Returns 0 if the element is schemas valid, a positive error code
7956 * number otherwise and -1 in case of internal or API error.
7957 */
7958static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007959xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7960{
Daniel Veillard4255d502002-04-16 15:50:10 +00007961 xmlNodePtr child;
7962 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007963 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00007964 xmlSchemaElementPtr decl;
Daniel Veillard3646d642004-06-02 19:19:14 +00007965 int ret;
7966 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
7967
7968 /*
7969 * TODO: Look into "xmlSchemaValidateElement" for missing parts, which should
7970 * go in here as well.
7971 */
7972
7973 /* TODO: Is this one called always with an element declaration as the
7974 * context's type?
7975 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007976
7977 oldregexp = ctxt->regexp;
7978
7979 child = ctxt->node;
7980 type = ctxt->type;
7981
7982 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00007983 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7984 "Internal error: xmlSchemaValidateElementType\n",
7985 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007986 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007987 }
7988 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007989 if (type->minOccurs > 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007990 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
7991 "Element %s: missing child %s\n",
7992 node->name, type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007993 }
7994 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00007995 }
7996
7997 /*
7998 * Verify the element matches
7999 */
8000 if (!xmlStrEqual(child->name, type->name)) {
William M. Bracke7091952004-05-11 15:09:58 +00008001 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
8002 "Element %s: missing child %s found %s\n",
8003 node->name, type->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008004 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008005 }
8006 /*
8007 * Verify the attributes
8008 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008009
8010 attrs = ctxt->attr;
8011 attrTop = ctxt->attrTop;
8012
Daniel Veillard4255d502002-04-16 15:50:10 +00008013 xmlSchemaRegisterAttributes(ctxt, child->properties);
Daniel Veillard3646d642004-06-02 19:19:14 +00008014
8015 /*
8016 * An element declaration does not hold any information about
8017 * attributes; thus, the following was removed.
8018 */
8019 /* xmlSchemaValidateAttributes(ctxt, child, type->attributes); */
8020
Daniel Veillard4255d502002-04-16 15:50:10 +00008021 /*
8022 * Verify the element content recursively
8023 */
8024 decl = (xmlSchemaElementPtr) type;
8025 oldregexp = ctxt->regexp;
8026 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008027 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
8028 (xmlRegExecCallbacks)
8029 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008030#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008031 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008032#endif
8033 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008034 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
8035 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00008036
8037 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008038 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008039#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008040 xmlGenericError(xmlGenericErrorContext,
8041 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00008042#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008043 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00008044 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
8045 "Element %s content check failed\n",
8046 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008047 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00008048 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
8049 "Element %s content check failure\n",
8050 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008051#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008052 } else {
8053 xmlGenericError(xmlGenericErrorContext,
8054 "Element %s content check succeeded\n",
8055 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008056
8057#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008058 }
8059 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00008060 }
8061 /*
8062 * Verify that all attributes were Schemas-validated
8063 */
8064 xmlSchemaCheckAttributes(ctxt, node);
Daniel Veillard3646d642004-06-02 19:19:14 +00008065 if (ctxt->attr != NULL)
8066 xmlSchemaFreeAttributeStates(ctxt->attr);
8067 ctxt->attr = attrs;
8068 ctxt->attrTop = attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +00008069 ctxt->regexp = oldregexp;
Daniel Veillard4255d502002-04-16 15:50:10 +00008070 ctxt->node = child;
8071 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008072 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008073}
8074
8075/**
8076 * xmlSchemaValidateBasicType:
8077 * @ctxt: a schema validation context
8078 * @node: the top node.
8079 *
8080 * Validate the content of an element expected to be a basic type type
8081 *
8082 * Returns 0 if the element is schemas valid, a positive error code
8083 * number otherwise and -1 in case of internal or API error.
8084 */
8085static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008086xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
8087{
Daniel Veillard4255d502002-04-16 15:50:10 +00008088 int ret;
8089 xmlNodePtr child, cur;
8090 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008091 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00008092
8093 child = ctxt->node;
8094 type = ctxt->type;
8095
8096 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00008097 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
8098 "Internal error: xmlSchemaValidateBasicType\n",
8099 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008100 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008101 }
8102 /*
8103 * First check the content model of the node.
8104 */
8105 cur = child;
8106 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008107 switch (cur->type) {
8108 case XML_TEXT_NODE:
8109 case XML_CDATA_SECTION_NODE:
8110 case XML_PI_NODE:
8111 case XML_COMMENT_NODE:
8112 case XML_XINCLUDE_START:
8113 case XML_XINCLUDE_END:
8114 break;
8115 case XML_ENTITY_REF_NODE:
8116 case XML_ENTITY_NODE:
8117 TODO break;
8118 case XML_ELEMENT_NODE:
William M. Bracke7091952004-05-11 15:09:58 +00008119 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
8120 "Element %s: child %s should not be present\n",
8121 node->name, cur->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008122 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008123 case XML_ATTRIBUTE_NODE:
8124 case XML_DOCUMENT_NODE:
8125 case XML_DOCUMENT_TYPE_NODE:
8126 case XML_DOCUMENT_FRAG_NODE:
8127 case XML_NOTATION_NODE:
8128 case XML_HTML_DOCUMENT_NODE:
8129 case XML_DTD_NODE:
8130 case XML_ELEMENT_DECL:
8131 case XML_ATTRIBUTE_DECL:
8132 case XML_ENTITY_DECL:
8133 case XML_NAMESPACE_DECL:
8134#ifdef LIBXML_DOCB_ENABLED
8135 case XML_DOCB_DOCUMENT_NODE:
8136#endif
William M. Bracke7091952004-05-11 15:09:58 +00008137 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
8138 "Element %s: node type of node unexpected here\n",
8139 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008140 return (ctxt->err);
8141 }
8142 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008143 }
8144 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008145 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008146 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008147 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00008148
8149 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008150 xmlSchemaFreeValue(ctxt->value);
8151 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008152 }
8153 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
8154 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008155 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00008156 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +00008157 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
8158 "Element %s: failed to validate basic type %s\n",
8159 node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008160 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008161 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00008162}
8163
8164/**
8165 * xmlSchemaValidateComplexType:
8166 * @ctxt: a schema validation context
8167 * @node: the top node.
8168 *
8169 * Validate the content of an element expected to be a complex type type
8170 * xmlschema-1.html#cvc-complex-type
8171 * Validation Rule: Element Locally Valid (Complex Type)
8172 *
8173 * Returns 0 if the element is schemas valid, a positive error code
8174 * number otherwise and -1 in case of internal or API error.
8175 */
8176static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008177xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
8178{
Daniel Veillard4255d502002-04-16 15:50:10 +00008179 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00008180 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008181 int ret;
8182
Daniel Veillard3646d642004-06-02 19:19:14 +00008183 /* TODO: Handle xsd:restriction & xsd:extension */
8184
Daniel Veillard4255d502002-04-16 15:50:10 +00008185 child = ctxt->node;
8186 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00008187 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00008188
Daniel Veillard4255d502002-04-16 15:50:10 +00008189 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008190 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008191 if (type->baseType != NULL) {
8192 } else if (child != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008193 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY,
8194 "Element %s is supposed to be empty\n",
8195 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008196 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008197 /* Removed due to changes of attribute validation:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008198 if (type->attributes != NULL) {
8199 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
8200 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008201 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008202 subtype = type->subtypes;
8203 while (subtype != NULL) {
8204 ctxt->type = subtype;
8205 xmlSchemaValidateComplexType(ctxt, node);
8206 subtype = subtype->next;
8207 }
8208 break;
8209 case XML_SCHEMA_CONTENT_ELEMENTS:
8210 case XML_SCHEMA_CONTENT_MIXED:
8211 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
8212 /*
8213 * Skip ignorable nodes in that context
8214 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008215 /* ComplexType, ComplexContent */
8216 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008217 child = xmlSchemaSkipIgnored(ctxt, type, child);
8218 while (child != NULL) {
8219 if (child->type == XML_ELEMENT_NODE) {
8220 ret = xmlRegExecPushString(ctxt->regexp,
8221 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00008222#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008223 if (ret < 0)
8224 xmlGenericError(xmlGenericErrorContext,
8225 " --> %s Error\n", child->name);
8226 else
8227 xmlGenericError(xmlGenericErrorContext,
8228 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008229#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008230 }
8231 child = child->next;
8232 /*
8233 * Skip ignorable nodes in that context
8234 */
8235 child = xmlSchemaSkipIgnored(ctxt, type, child);
8236 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008237 }
8238
William M. Bracke7091952004-05-11 15:09:58 +00008239 if (((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
8240 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS)) &&
8241 (type->subtypes != NULL)) {
8242 TODO
8243 }
8244
Daniel Veillard3646d642004-06-02 19:19:14 +00008245 /* Removed due to changes of attribute validation:
Daniel Veillardf2a12832003-11-24 13:04:35 +00008246 if (type->attributes != NULL) {
8247 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
8248 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008249 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008250 break;
8251 case XML_SCHEMA_CONTENT_BASIC:{
8252 if (type->subtypes != NULL) {
8253 ctxt->type = type->subtypes;
8254 xmlSchemaValidateComplexType(ctxt, node);
8255 }
8256 if (type->baseType != NULL) {
8257 ctxt->type = type->baseType;
William M. Bracke7091952004-05-11 15:09:58 +00008258 if (type->baseType->type == XML_SCHEMA_TYPE_BASIC)
8259 xmlSchemaValidateBasicType(ctxt, node);
8260 else if (type->baseType->type == XML_SCHEMA_TYPE_COMPLEX)
8261 xmlSchemaValidateComplexType(ctxt, node);
Daniel Veillard3646d642004-06-02 19:19:14 +00008262 /* TODO: This might be incorrect. */
William M. Bracke7091952004-05-11 15:09:58 +00008263 else if (type->baseType->type == XML_SCHEMA_TYPE_SIMPLE)
8264 xmlSchemaValidateSimpleType(ctxt, node);
8265 else
8266 xmlGenericError(xmlGenericErrorContext,
8267 "unexpected content type of base: %d\n",
8268 type->contentType);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008269 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008270 /* Removed due to changes of attribute validation:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008271 if (type->attributes != NULL) {
8272 xmlSchemaValidateAttributes(ctxt, node,
8273 type->attributes);
8274 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008275 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008276 ctxt->type = type;
8277 break;
8278 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008279 case XML_SCHEMA_CONTENT_SIMPLE:{
8280 if (type->subtypes != NULL) {
8281 ctxt->type = type->subtypes;
8282 xmlSchemaValidateComplexType(ctxt, node);
8283 }
8284 if (type->baseType != NULL) {
8285 ctxt->type = type->baseType;
8286 xmlSchemaValidateComplexType(ctxt, node);
8287 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008288 /* Removed due to changes of attribute validation:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008289 if (type->attributes != NULL) {
8290 xmlSchemaValidateAttributes(ctxt, node,
8291 type->attributes);
8292 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008293 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008294 ctxt->type = type;
8295 break;
8296 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008297 default:
8298 TODO xmlGenericError(xmlGenericErrorContext,
8299 "unimplemented content type %d\n",
8300 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00008301 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008302 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
8303 xmlSchemaValidateAttributes(ctxt, node, type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008304 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008305}
8306
8307/**
8308 * xmlSchemaValidateContent:
8309 * @ctxt: a schema validation context
8310 * @elem: an element
8311 * @type: the type declaration
8312 *
8313 * Validate the content of an element against the type.
8314 *
8315 * Returns 0 if the element is schemas valid, a positive error code
8316 * number otherwise and -1 in case of internal or API error.
8317 */
8318static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008319xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
8320{
Daniel Veillard4255d502002-04-16 15:50:10 +00008321 xmlNodePtr child;
8322 xmlSchemaTypePtr type;
8323
8324 child = ctxt->node;
8325 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00008326 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00008327
Daniel Veillard3646d642004-06-02 19:19:14 +00008328 /*
8329 * Removed, since redundant.
8330 */
8331 /* xmlSchemaValidateAttributes(ctxt, node, type->attributes); */
Daniel Veillard82bbbd42003-05-11 20:16:09 +00008332 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00008333
Daniel Veillard4255d502002-04-16 15:50:10 +00008334 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008335 case XML_SCHEMA_TYPE_ANY:
8336 /* Any type will do it, fine */
8337 TODO /* handle recursivity */
8338 break;
8339 case XML_SCHEMA_TYPE_COMPLEX:
8340 xmlSchemaValidateComplexType(ctxt, node);
8341 break;
8342 case XML_SCHEMA_TYPE_ELEMENT:{
8343 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
8344
8345 /*
8346 * Handle element reference here
8347 */
8348 if (decl->ref != NULL) {
8349 if (decl->refDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008350 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
8351 "Internal error: element reference %s "
8352 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008353 return (-1);
8354 }
8355 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
8356 decl = decl->refDecl;
8357 }
William M. Bracke7091952004-05-11 15:09:58 +00008358 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008359 xmlSchemaValidateElementType(ctxt, node);
8360 ctxt->type = type;
8361 break;
8362 }
8363 case XML_SCHEMA_TYPE_BASIC:
8364 xmlSchemaValidateBasicType(ctxt, node);
8365 break;
8366 case XML_SCHEMA_TYPE_FACET:
8367 TODO break;
8368 case XML_SCHEMA_TYPE_SIMPLE:
8369 xmlSchemaValidateSimpleType(ctxt, node);
8370 break;
8371 case XML_SCHEMA_TYPE_SEQUENCE:
8372 TODO break;
8373 case XML_SCHEMA_TYPE_CHOICE:
8374 TODO break;
8375 case XML_SCHEMA_TYPE_ALL:
8376 TODO break;
8377 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8378 TODO break;
8379 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8380 TODO break;
8381 case XML_SCHEMA_TYPE_UR:
8382 TODO break;
8383 case XML_SCHEMA_TYPE_RESTRICTION:
8384 /*xmlSchemaValidateRestrictionType(ctxt, node); */
8385 TODO break;
8386 case XML_SCHEMA_TYPE_EXTENSION:
8387 TODO break;
8388 case XML_SCHEMA_TYPE_ATTRIBUTE:
8389 TODO break;
8390 case XML_SCHEMA_TYPE_GROUP:
8391 TODO break;
8392 case XML_SCHEMA_TYPE_NOTATION:
8393 TODO break;
8394 case XML_SCHEMA_TYPE_LIST:
8395 TODO break;
8396 case XML_SCHEMA_TYPE_UNION:
8397 TODO break;
8398 case XML_SCHEMA_FACET_MININCLUSIVE:
8399 TODO break;
8400 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8401 TODO break;
8402 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8403 TODO break;
8404 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8405 TODO break;
8406 case XML_SCHEMA_FACET_TOTALDIGITS:
8407 TODO break;
8408 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8409 TODO break;
8410 case XML_SCHEMA_FACET_PATTERN:
8411 TODO break;
8412 case XML_SCHEMA_FACET_ENUMERATION:
8413 TODO break;
8414 case XML_SCHEMA_FACET_WHITESPACE:
8415 TODO break;
8416 case XML_SCHEMA_FACET_LENGTH:
8417 TODO break;
8418 case XML_SCHEMA_FACET_MAXLENGTH:
8419 TODO break;
8420 case XML_SCHEMA_FACET_MINLENGTH:
8421 TODO break;
8422 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
8423 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +00008424 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8425 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00008426 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008427 /*
8428 * Removed, since redundant.
8429 */
8430 /* xmlSchemaValidateAttributes(ctxt, node, type->attributes); */
Daniel Veillard4255d502002-04-16 15:50:10 +00008431
8432 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008433 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008434 ctxt->node = ctxt->node->next;
8435 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008436 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008437}
8438
8439/**
8440 * xmlSchemaValidateType:
8441 * @ctxt: a schema validation context
8442 * @elem: an element
8443 * @type: the list of type declarations
8444 *
8445 * Validate the content of an element against the types.
8446 *
8447 * Returns 0 if the element is schemas valid, a positive error code
8448 * number otherwise and -1 in case of internal or API error.
8449 */
8450static int
8451xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008452 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
8453{
Daniel Veillard4255d502002-04-16 15:50:10 +00008454 xmlChar *nil;
8455
Daniel Veillard2db8c122003-07-08 12:16:59 +00008456 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008457 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00008458
Daniel Veillard3646d642004-06-02 19:19:14 +00008459 /* This one is called by "xmlSchemaValidateElementType" and
8460 * "xmlSchemaValidateElement".
8461 */
8462
Daniel Veillard4255d502002-04-16 15:50:10 +00008463 /*
8464 * 3.3.4 : 2
8465 */
8466 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
William M. Bracke7091952004-05-11 15:09:58 +00008467 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
8468 "Element declaration %s is abstract\n",
8469 elemDecl->name, NULL);
8470 /* Changed, since the element declaration is abstract and not
8471 * the element itself. */
8472 /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
8473 "Element %s is abstract\n", elem->name, NULL); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008474 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008475 }
8476 /*
8477 * 3.3.4: 3
8478 */
8479 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
8480 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008481 /* 3.3.4: 3.2 */
8482 if (xmlStrEqual(nil, BAD_CAST "true")) {
8483 if (elem->children != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008484 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
8485 "Element %s is not empty\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008486 return (ctxt->err);
8487 }
8488 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
8489 (elemDecl->value != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00008490 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
8491 "Empty element %s cannot get a fixed value\n",
8492 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008493 return (ctxt->err);
8494 }
8495 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008496 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008497 /* 3.3.4: 3.1 */
8498 if (nil != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008499 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
8500 "Element %s with xs:nil but not nillable\n",
8501 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008502 xmlFree(nil);
8503 return (ctxt->err);
8504 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008505 }
8506
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008507 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00008508
8509 ctxt->type = elemDecl->subtypes;
8510 ctxt->node = elem->children;
8511 xmlSchemaValidateContent(ctxt, elem);
Daniel Veillard3646d642004-06-02 19:19:14 +00008512 /* Removed, since an element declaration does not hold any attribute
8513 * declarations */
8514 /* xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008515
8516 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008517}
8518
8519
8520/**
8521 * xmlSchemaValidateAttributes:
8522 * @ctxt: a schema validation context
8523 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +00008524 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +00008525 *
8526 * Validate the attributes of an element.
8527 *
8528 * Returns 0 if the element is schemas valid, a positive error code
8529 * number otherwise and -1 in case of internal or API error.
8530 */
8531static int
Daniel Veillard3646d642004-06-02 19:19:14 +00008532xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008533{
Daniel Veillard3646d642004-06-02 19:19:14 +00008534 int ret;
8535 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +00008536 xmlChar *value;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +00008537 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +00008538 xmlSchemaAttributeLinkPtr attrUse;
8539 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00008540 int found;
William M. Brack803812b2004-06-03 02:11:24 +00008541 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00008542#ifdef DEBUG_ATTR_VALIDATION
8543 int redundant = 0;
8544#endif
8545 if (type->type != XML_SCHEMA_TYPE_COMPLEX) {
8546 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INTERNAL,
8547 "Internal error: xmlSchemaValidateAttributes: "
8548 "given type \"%s\"is not a complexType\n",
8549 type->name, NULL);
8550 return(-1);
8551 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008552
Daniel Veillard3646d642004-06-02 19:19:14 +00008553 if ((type->attributeUses == NULL) && (type->attributeWildcard == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008554 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008555
8556 attrUse = type->attributeUses;
8557
8558 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00008559 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00008560 attrDecl = attrUse->attr;
8561#ifdef DEBUG_ATTR_VALIDATION
8562 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
8563 printf("attr use - use: %d\n", attrDecl->occurs);
8564#endif
8565 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
8566
8567 if (curState->decl == attrUse->attr) {
8568#ifdef DEBUG_ATTR_VALIDATION
8569 redundant = 1;
8570#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008571 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008572 attr = curState->attr;
8573#ifdef DEBUG_ATTR_VALIDATION
8574 printf("attr - name: %s\n", attr->name);
8575 if (attr->ns != NULL)
8576 printf("attr - ns: %s\n", attr->ns->href);
8577 else
8578 printf("attr - ns: none\n");
8579#endif
8580 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008581 if (attr == NULL)
8582 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +00008583 if (attrDecl->ref != NULL) {
8584 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008585 continue;
8586 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008587 if ((attrDecl->refNs == NULL) ||
8588 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008589 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +00008590 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008591 continue;
8592 }
8593 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00008594 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008595 continue;
8596 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008597 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008598 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008599 if (attr->ns == NULL) {
8600 /*
William M. Bracke7091952004-05-11 15:09:58 +00008601 * accept an unqualified attribute only if the target
8602 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008603 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008604 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +00008605 /*
8606 * This check was removed, since the target namespace
8607 * was evaluated during parsing and already took
8608 * "attributeFormDefault" into account.
8609 */
8610 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008611 continue;
8612 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00008613 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008614 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +00008615 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008616 attr->ns->href))
8617 continue;
8618 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008619 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008620#ifdef DEBUG_ATTR_VALIDATION
8621 printf("found\n");
8622#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00008623 found = 1;
Daniel Veillard50355f02004-06-08 17:52:16 +00008624 ctxt->cur = (xmlNodePtr) attr;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00008625
Daniel Veillard3646d642004-06-02 19:19:14 +00008626 if (attrDecl->subtypes == NULL) {
8627 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
8628 curState->decl = attrDecl;
8629 /*
8630 * This could be put into "xmlSchemaCheckAttributes" as well, but
8631 * since it reports an internal error, it better stays here to ease
8632 * debugging.
8633 */
William M. Bracke7091952004-05-11 15:09:58 +00008634 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
8635 "Internal error: attribute %s type not resolved\n",
8636 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008637 continue;
8638 }
8639 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00008640 ret = xmlSchemaValidateSimpleValue(ctxt, attrDecl->subtypes,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008641 value);
Daniel Veillard3646d642004-06-02 19:19:14 +00008642 if (ret != 0)
8643 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
8644 else
8645 curState->state = XML_SCHEMAS_ATTR_CHECKED;
8646 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008647 if (value != NULL) {
8648 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +00008649 }
8650 }
8651 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
8652 xmlSchemaAttrStatePtr tmp;
8653
8654#ifdef DEBUG_ATTR_VALIDATION
8655 printf("required attr not found\n");
8656#endif
8657 /*
8658 * Add a new dummy attribute state.
8659 */
8660 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
8661 if (tmp == NULL) {
8662 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
8663 return (-1);
8664 }
8665 tmp->attr = NULL;
8666 tmp->state = XML_SCHEMAS_ATTR_MISSING;
8667 tmp->decl = attrDecl;
8668 tmp->next = NULL;
8669
8670 if (reqAttrStates == NULL) {
8671 reqAttrStates = tmp;
8672 reqAttrStatesTop = tmp;
8673 } else {
8674 reqAttrStatesTop->next = tmp;
8675 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008676 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008677
8678 }
8679 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008680 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008681 /*
8682 * Add required attributes to the attribute states of the context.
8683 */
8684 if (reqAttrStates != NULL) {
8685 if (ctxt->attr == NULL) {
8686 ctxt->attr = reqAttrStates;
8687 } else {
8688 ctxt->attrTop->next = reqAttrStates;
8689 }
8690 ctxt->attrTop = reqAttrStatesTop;
8691 }
8692 /*
8693 * Process wildcards.
8694 */
8695 if (type->attributeWildcard != NULL) {
8696#ifdef DEBUG_ATTR_VALIDATION
8697 xmlSchemaWildcardNsPtr ns;
8698 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +00008699 if (type->attributeWildcard->processContents ==
8700 XML_SCHEMAS_ANY_LAX)
8701 printf("processContents: lax\n");
8702 else if (type->attributeWildcard->processContents ==
8703 XML_SCHEMAS_ANY_STRICT)
8704 printf("processContents: strict\n");
8705 else
8706 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +00008707 if (type->attributeWildcard->any)
8708 printf("type: any\n");
8709 else if (type->attributeWildcard->negNsSet != NULL) {
8710 printf("type: negated\n");
8711 if (type->attributeWildcard->negNsSet->value == NULL)
8712 printf("ns: (absent)\n");
8713 else
8714 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
8715 } else if (type->attributeWildcard->nsSet != NULL) {
8716 printf("type: set\n");
8717 ns = type->attributeWildcard->nsSet;
8718 while (ns != NULL) {
8719 if (ns->value == NULL)
8720 printf("ns: (absent)\n");
8721 else
8722 printf("ns: %s\n", ns->value);
8723 ns = ns->next;
8724 }
8725 } else
8726 printf("empty\n");
8727
Daniel Veillard8acdfbf2004-06-03 16:00:59 +00008728
8729#endif
Daniel Veillard3646d642004-06-02 19:19:14 +00008730 curState = ctxt->attr;
8731 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +00008732 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
8733 if (curState->attr->ns != NULL)
8734 nsURI = curState->attr->ns->href;
8735 else
8736 nsURI = NULL;
8737 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
8738 nsURI)) {
8739 /*
8740 * Handle processContents.
8741 */
8742 if ((type->attributeWildcard->processContents ==
8743 XML_SCHEMAS_ANY_LAX) ||
8744 (type->attributeWildcard->processContents ==
8745 XML_SCHEMAS_ANY_STRICT)) {
8746
8747 attr = curState->attr;
8748 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
8749 attr->name, nsURI);
8750 if (attrDecl != NULL) {
8751 value = xmlNodeListGetString(elem->doc, attr->children, 1);
8752 ret = xmlSchemaValidateSimpleValue(ctxt, attrDecl->subtypes,
8753 value);
8754 if (ret != 0)
8755 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
8756 else
8757 curState->state = XML_SCHEMAS_ATTR_CHECKED;
8758 curState->decl = attrDecl;
8759 if (value != NULL) {
8760 xmlFree(value);
8761 }
8762
8763 } else if (type->attributeWildcard->processContents ==
8764 XML_SCHEMAS_ANY_LAX) {
8765 curState->state = XML_SCHEMAS_ATTR_CHECKED;
8766 }
8767 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00008768 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +00008769 }
8770 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008771 curState = curState->next;
8772 }
8773 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008774#ifdef DEBUG_ATTR_VALIDATION
8775 if (redundant)
8776 xmlGenericError(xmlGenericErrorContext,
8777 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
8778 type->name);
8779#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008780 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008781}
8782
8783/**
8784 * xmlSchemaValidateElement:
8785 * @ctxt: a schema validation context
8786 * @elem: an element
8787 *
8788 * Validate an element in a tree
8789 *
8790 * Returns 0 if the element is schemas valid, a positive error code
8791 * number otherwise and -1 in case of internal or API error.
8792 */
8793static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008794xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
8795{
Daniel Veillard4255d502002-04-16 15:50:10 +00008796 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +00008797 int ret;
8798 xmlSchemaAttrStatePtr attrs, attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +00008799
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008800 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008801 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8802 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008803 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008804 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8805 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008806 }
8807 /*
8808 * special case whe elementFormDefault is unqualified for top-level elem.
8809 */
William M. Bracke7091952004-05-11 15:09:58 +00008810 /*
8811 * This was removed, since elementFormDefault does not apply to top-level
8812 * element declarations.
8813 */
8814 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008815 if ((elemDecl == NULL) && (elem->ns != NULL) &&
8816 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
8817 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
8818 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
8819 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8820 elem->name, NULL, NULL);
8821 }
William M. Bracke7091952004-05-11 15:09:58 +00008822 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008823
Daniel Veillard4255d502002-04-16 15:50:10 +00008824 /*
8825 * 3.3.4 : 1
8826 */
8827 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008828 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
8829 "Element %s not declared\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008830 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008831 }
8832 if (elemDecl->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008833 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
8834 "Element %s has no type\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008835 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008836 }
8837 /*
8838 * Verify the attributes
8839 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008840 attrs = ctxt->attr;
8841 attrTop = ctxt->attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +00008842 xmlSchemaRegisterAttributes(ctxt, elem->properties);
Daniel Veillard4255d502002-04-16 15:50:10 +00008843 /*
8844 * Verify the element content recursively
8845 */
8846 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008847 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
8848 (xmlRegExecCallbacks)
8849 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008850#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008851 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008852#endif
8853 }
8854 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008855 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008856 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008857#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008858 xmlGenericError(xmlGenericErrorContext,
8859 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008860#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008861 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00008862 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
8863 "Element %s content check failed\n",
8864 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008865 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00008866 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
8867 "Element %s content check failed\n",
8868 elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008869#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008870 } else {
8871 xmlGenericError(xmlGenericErrorContext,
8872 "Element %s content check succeeded\n",
8873 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008874
8875#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008876 }
8877 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00008878 }
8879 /*
8880 * Verify that all attributes were Schemas-validated
8881 */
8882 xmlSchemaCheckAttributes(ctxt, elem);
Daniel Veillard3646d642004-06-02 19:19:14 +00008883 if (ctxt->attr != NULL)
8884 xmlSchemaFreeAttributeStates(ctxt->attr);
8885 ctxt->attr = attrs;
8886 ctxt->attrTop = attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008887
8888 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008889}
8890
8891/**
8892 * xmlSchemaValidateDocument:
8893 * @ctxt: a schema validation context
8894 * @doc: a parsed document tree
8895 *
8896 * Validate a document tree in memory.
8897 *
8898 * Returns 0 if the document is schemas valid, a positive error code
8899 * number otherwise and -1 in case of internal or API error.
8900 */
8901static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008902xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
8903{
Daniel Veillard4255d502002-04-16 15:50:10 +00008904 xmlNodePtr root;
8905 xmlSchemaElementPtr elemDecl;
8906
8907 root = xmlDocGetRootElement(doc);
8908 if (root == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008909 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
8910 "document has no root\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008911 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008912 }
William M. Bracke7091952004-05-11 15:09:58 +00008913
Daniel Veillard4255d502002-04-16 15:50:10 +00008914 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008915 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8916 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008917 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008918 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8919 root->name, NULL, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00008920
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008921 /*
8922 * special case whe elementFormDefault is unqualified for top-level elem.
8923 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008924 /* Removed, since elementFormDefault does not apply to top level
8925 * elements */
8926 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008927 if ((elemDecl == NULL) && (root->ns != NULL) &&
8928 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
8929 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
8930 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8931 root->name, NULL, NULL);
8932 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008933 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008934
Daniel Veillard4255d502002-04-16 15:50:10 +00008935 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008936 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
8937 "Element %s not declared\n", root->name, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00008938 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00008939 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
Daniel Veillard3646d642004-06-02 19:19:14 +00008940 "Root element %s not global\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008941 }
8942 /*
8943 * Okay, start the recursive validation
8944 */
8945 xmlSchemaValidateElement(ctxt, root);
8946
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008947 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008948}
8949
8950/************************************************************************
8951 * *
8952 * SAX Validation code *
8953 * *
8954 ************************************************************************/
8955
8956/************************************************************************
8957 * *
8958 * Validation interfaces *
8959 * *
8960 ************************************************************************/
8961
8962/**
8963 * xmlSchemaNewValidCtxt:
8964 * @schema: a precompiled XML Schemas
8965 *
8966 * Create an XML Schemas validation context based on the given schema
8967 *
8968 * Returns the validation context or NULL in case of error
8969 */
8970xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008971xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
8972{
Daniel Veillard4255d502002-04-16 15:50:10 +00008973 xmlSchemaValidCtxtPtr ret;
8974
8975 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
8976 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008977 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008978 return (NULL);
8979 }
8980 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
8981 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +00008982 /*
8983 * Removed due to changes of the attribute state list.
William M. Brack803812b2004-06-03 02:11:24 +00008984 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008985 /* ret->attrNr = 0; */
8986 /* ret->attrMax = 10; */
8987 /* ret->attrBase = NULL; */
8988 ret->attrTop = NULL;
8989 ret->attr = NULL;
8990 /*
8991 * Removed due to changes of the attribute state list.
William M. Brack803812b2004-06-03 02:11:24 +00008992 *
Daniel Veillard4255d502002-04-16 15:50:10 +00008993 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008994 sizeof
8995 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00008996 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008997 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
8998 free(ret);
8999 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009000 }
9001 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
Daniel Veillard3646d642004-06-02 19:19:14 +00009002 */
9003
Daniel Veillard4255d502002-04-16 15:50:10 +00009004 return (ret);
9005}
9006
9007/**
9008 * xmlSchemaFreeValidCtxt:
9009 * @ctxt: the schema validation context
9010 *
9011 * Free the resources associated to the schema validation context
9012 */
9013void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009014xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
9015{
Daniel Veillard4255d502002-04-16 15:50:10 +00009016 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009017 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009018 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00009019 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00009020 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009021 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00009022 xmlFree(ctxt);
9023}
9024
9025/**
9026 * xmlSchemaSetValidErrors:
9027 * @ctxt: a schema validation context
9028 * @err: the error function
9029 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00009030 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00009031 *
9032 * Set the error and warning callback informations
9033 */
9034void
9035xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009036 xmlSchemaValidityErrorFunc err,
9037 xmlSchemaValidityWarningFunc warn, void *ctx)
9038{
Daniel Veillard4255d502002-04-16 15:50:10 +00009039 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009040 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009041 ctxt->error = err;
9042 ctxt->warning = warn;
9043 ctxt->userData = ctx;
9044}
9045
9046/**
9047 * xmlSchemaValidateDoc:
9048 * @ctxt: a schema validation context
9049 * @doc: a parsed document tree
9050 *
9051 * Validate a document tree in memory.
9052 *
9053 * Returns 0 if the document is schemas valid, a positive error code
9054 * number otherwise and -1 in case of internal or API error.
9055 */
9056int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009057xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
9058{
Daniel Veillard4255d502002-04-16 15:50:10 +00009059 int ret;
9060
9061 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009062 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009063
9064 ctxt->doc = doc;
9065 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009066 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009067}
9068
9069/**
9070 * xmlSchemaValidateStream:
9071 * @ctxt: a schema validation context
9072 * @input: the input to use for reading the data
9073 * @enc: an optional encoding information
9074 * @sax: a SAX handler for the resulting events
9075 * @user_data: the context to provide to the SAX handler.
9076 *
9077 * Validate a document tree in memory.
9078 *
9079 * Returns 0 if the document is schemas valid, a positive error code
9080 * number otherwise and -1 in case of internal or API error.
9081 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009082int
Daniel Veillard4255d502002-04-16 15:50:10 +00009083xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009084 xmlParserInputBufferPtr input, xmlCharEncoding enc,
9085 xmlSAXHandlerPtr sax, void *user_data)
9086{
Daniel Veillard4255d502002-04-16 15:50:10 +00009087 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009088 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009089 ctxt->input = input;
9090 ctxt->enc = enc;
9091 ctxt->sax = sax;
9092 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009093 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00009094}
9095
9096#endif /* LIBXML_SCHEMAS_ENABLED */