blob: 17f612f1835a38510d7bfa9358740885efbbff57 [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
5363static int
5364xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
5365 xmlSchemaWildcardPtr *dest,
5366 xmlSchemaWildcardPtr source)
5367{
5368 xmlSchemaWildcardNsPtr cur, tmp, last;
5369
5370 if ((source == NULL) || (*dest == NULL))
5371 return(-1);
5372 (*dest)->any = source->any;
5373 cur = source->nsSet;
5374 last = NULL;
5375 while (cur != NULL) {
5376 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5377 if (tmp == NULL)
5378 return(-1);
5379 tmp->value = cur->value;
5380 if (last == NULL)
5381 (*dest)->nsSet = tmp;
5382 else
5383 last->next = tmp;
5384 last = tmp;
5385 cur = cur->next;
5386 }
5387 if ((*dest)->negNsSet != NULL)
5388 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
5389 if (source->negNsSet != NULL) {
5390 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5391 if ((*dest)->negNsSet == NULL)
5392 return(-1);
5393 (*dest)->negNsSet->value = source->negNsSet->value;
5394 } else
5395 (*dest)->negNsSet = NULL;
5396 return(0);
5397}
5398
5399static int
5400xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
5401 xmlSchemaWildcardPtr completeWild,
5402 xmlSchemaWildcardPtr curWild)
5403{
5404 xmlSchemaWildcardNsPtr cur, curB, tmp;
5405
5406 /*
5407 * 1 If O1 and O2 are the same value, then that value must be the
5408 * value.
5409 */
5410 if ((completeWild->any == curWild->any) &&
5411 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
5412 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
5413
5414 if ((completeWild->negNsSet == NULL) ||
5415 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
5416
5417 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00005418 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00005419
5420 /*
5421 * Check equality of sets.
5422 */
5423 cur = completeWild->nsSet;
5424 while (cur != NULL) {
5425 found = 0;
5426 curB = curWild->nsSet;
5427 while (curB != NULL) {
5428 if (cur->value == curB->value) {
5429 found = 1;
5430 break;
5431 }
5432 curB = curB->next;
5433 }
5434 if (!found)
5435 break;
5436 cur = cur->next;
5437 }
5438 if (found)
5439 return(0);
5440 } else
5441 return(0);
5442 }
5443 }
5444 /*
5445 * 2 If either O1 or O2 is any, then any must be the value
5446 */
5447 if ((completeWild->any != curWild->any) && (completeWild->any)) {
5448 if (completeWild->any == 0) {
5449 completeWild->any = 1;
5450 if (completeWild->nsSet != NULL) {
5451 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5452 completeWild->nsSet = NULL;
5453 }
5454 if (completeWild->negNsSet != NULL) {
5455 xmlFree(completeWild->negNsSet);
5456 completeWild->negNsSet = NULL;
5457 }
5458 }
5459 }
5460 /*
5461 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
5462 * then the union of those sets must be the value.
5463 */
5464 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
5465 int found;
5466 xmlSchemaWildcardNsPtr start;
5467
5468 cur = curWild->nsSet;
5469 start = completeWild->nsSet;
5470 while (cur != NULL) {
5471 found = 0;
5472 curB = start;
5473 while (curB != NULL) {
5474 if (cur->value == curB->value) {
5475 found = 1;
5476 break;
5477 }
5478 curB = curB->next;
5479 }
5480 if (!found) {
5481 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5482 if (tmp == NULL)
5483 return (-1);
5484 tmp->value = cur->value;
5485 tmp->next = completeWild->nsSet;
5486 completeWild->nsSet = tmp;
5487 }
5488 cur = cur->next;
5489 }
5490
5491 return(0);
5492 }
5493 /*
5494 * 4 If the two are negations of different values (namespace names
5495 * or ·absent·), then a pair of not and ·absent· must be the value.
5496 */
5497 if ((completeWild->negNsSet != NULL) &&
5498 (curWild->negNsSet != NULL) &&
5499 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
5500 completeWild->negNsSet->value = NULL;
5501 }
5502 /*
5503 * 5.
5504 */
5505 if (((completeWild->negNsSet != NULL) &&
5506 (completeWild->negNsSet->value != NULL) &&
5507 (curWild->nsSet != NULL)) ||
5508 ((curWild->negNsSet != NULL) &&
5509 (curWild->negNsSet->value != NULL) &&
5510 (completeWild->nsSet != NULL))) {
5511
5512 int nsFound, absentFound = 0;
5513
5514 if (completeWild->nsSet != NULL) {
5515 cur = completeWild->nsSet;
5516 curB = curWild->negNsSet;
5517 } else {
5518 cur = curWild->nsSet;
5519 curB = completeWild->negNsSet;
5520 }
5521 nsFound = 0;
5522 while (cur != NULL) {
5523 if (cur->value == NULL)
5524 absentFound = 1;
5525 else if (cur->value == curB->value)
5526 nsFound = 1;
5527 if (nsFound && absentFound)
5528 break;
5529 cur = cur->next;
5530 }
5531
5532 if (nsFound && absentFound) {
5533 /*
5534 * 5.1 If the set S includes both the negated namespace
5535 * name and ·absent·, then any must be the value.
5536 */
5537 completeWild->any = 1;
5538 if (completeWild->nsSet != NULL) {
5539 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5540 completeWild->nsSet = NULL;
5541 }
5542 if (completeWild->negNsSet != NULL) {
5543 xmlFree(completeWild->negNsSet);
5544 completeWild->negNsSet = NULL;
5545 }
5546 } else if (nsFound && (!absentFound)) {
5547 /*
5548 * 5.2 If the set S includes the negated namespace name
5549 * but not ·absent·, then a pair of not and ·absent· must
5550 * be the value.
5551 */
5552 if (completeWild->nsSet != NULL) {
5553 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5554 completeWild->nsSet = NULL;
5555 }
5556 if (completeWild->negNsSet == NULL) {
5557 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5558 if (completeWild->negNsSet == NULL)
5559 return (-1);
5560 }
5561 completeWild->negNsSet->value = NULL;
5562 } else if ((!nsFound) && absentFound) {
5563 /*
5564 * 5.3 If the set S includes ·absent· but not the negated
5565 * namespace name, then the union is not expressible.
5566 */
5567 xmlSchemaPErr(ctxt, completeWild->node,
5568 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
5569 "The union of the wilcard is not expressible\n",
5570 NULL, NULL);
5571 return(0);
5572 } else if ((!nsFound) && (!absentFound)) {
5573 /*
5574 * 5.4 If the set S does not include either the negated namespace
5575 * name or ·absent·, then whichever of O1 or O2 is a pair of not
5576 * and a namespace name must be the value.
5577 */
5578 if (completeWild->negNsSet == NULL) {
5579 if (completeWild->nsSet != NULL) {
5580 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5581 completeWild->nsSet = NULL;
5582 }
5583 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5584 if (completeWild->negNsSet == NULL)
5585 return (-1);
5586 completeWild->negNsSet->value = curWild->negNsSet->value;
5587 }
5588 }
5589 return (0);
5590 }
5591 /*
5592 * 6.
5593 */
5594 if (((completeWild->negNsSet != NULL) &&
5595 (completeWild->negNsSet->value == NULL) &&
5596 (curWild->nsSet != NULL)) ||
5597 ((curWild->negNsSet != NULL) &&
5598 (curWild->negNsSet->value == NULL) &&
5599 (completeWild->nsSet != NULL))) {
5600
5601 if (completeWild->nsSet != NULL) {
5602 cur = completeWild->nsSet;
5603 } else {
5604 cur = curWild->nsSet;
5605 }
5606 while (cur != NULL) {
5607 if (cur->value == NULL) {
5608 /*
5609 * 6.1 If the set S includes ·absent·, then any must be the
5610 * value.
5611 */
5612 completeWild->any = 1;
5613 if (completeWild->nsSet != NULL) {
5614 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5615 completeWild->nsSet = NULL;
5616 }
5617 if (completeWild->negNsSet != NULL) {
5618 xmlFree(completeWild->negNsSet);
5619 completeWild->negNsSet = NULL;
5620 }
5621 return (0);
5622 }
5623 cur = cur->next;
5624 }
5625 if (completeWild->negNsSet == NULL) {
5626 /*
5627 * 6.2 If the set S does not include ·absent·, then a pair of not
5628 * and ·absent· must be the value.
5629 */
5630 if (completeWild->nsSet != NULL) {
5631 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5632 completeWild->nsSet = NULL;
5633 }
5634 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5635 if (completeWild->negNsSet == NULL)
5636 return (-1);
5637 completeWild->negNsSet->value = NULL;
5638 }
5639 return (0);
5640 }
5641 return (0);
5642
5643}
5644
5645static int
5646xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
5647 xmlSchemaWildcardPtr completeWild,
5648 xmlSchemaWildcardPtr curWild)
5649{
William M. Brack803812b2004-06-03 02:11:24 +00005650 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00005651
5652 /*
5653 * 1 If O1 and O2 are the same value, then that value must be the
5654 * value.
5655 */
5656 if ((completeWild->any == curWild->any) &&
5657 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
5658 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
5659
5660 if ((completeWild->negNsSet == NULL) ||
5661 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
5662
5663 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00005664 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00005665
5666 /*
5667 * Check equality of sets.
5668 */
5669 cur = completeWild->nsSet;
5670 while (cur != NULL) {
5671 found = 0;
5672 curB = curWild->nsSet;
5673 while (curB != NULL) {
5674 if (cur->value == curB->value) {
5675 found = 1;
5676 break;
5677 }
5678 curB = curB->next;
5679 }
5680 if (!found)
5681 break;
5682 cur = cur->next;
5683 }
5684 if (found)
5685 return(0);
5686 } else
5687 return(0);
5688 }
5689 }
5690 /*
5691 * 2 If either O1 or O2 is any, then the other must be the value.
5692 */
5693 if ((completeWild->any != curWild->any) && (completeWild->any)) {
5694 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
5695 return(-1);
5696 return(0);
5697 }
5698 /*
5699 * 3 If either O1 or O2 is a pair of not and a value (a namespace
5700 * name or ·absent·) and the other is a set of (namespace names or
5701 * ·absent·), then that set, minus the negated value if it was in
5702 * the set, minus ·absent· if it was in the set, must be the value.
5703 */
5704 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
5705 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
5706 const xmlChar *neg;
5707
5708 if (completeWild->nsSet == NULL) {
5709 neg = completeWild->negNsSet->value;
5710 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
5711 return(-1);
5712 } else
5713 neg = curWild->negNsSet->value;
5714 /*
5715 * Remove absent and negated.
5716 */
5717 prev = NULL;
5718 cur = completeWild->nsSet;
5719 while (cur != NULL) {
5720 if (cur->value == NULL) {
5721 if (prev == NULL)
5722 completeWild->nsSet = cur->next;
5723 else
5724 prev->next = cur->next;
5725 xmlFree(cur);
5726 break;
5727 }
5728 prev = cur;
5729 cur = cur->next;
5730 }
5731 if (neg != NULL) {
5732 prev = NULL;
5733 cur = completeWild->nsSet;
5734 while (cur != NULL) {
5735 if (cur->value == neg) {
5736 if (prev == NULL)
5737 completeWild->nsSet = cur->next;
5738 else
5739 prev->next = cur->next;
5740 xmlFree(cur);
5741 break;
5742 }
5743 prev = cur;
5744 cur = cur->next;
5745 }
5746 }
5747
5748 return(0);
5749 }
5750 /*
5751 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
5752 * then the intersection of those sets must be the value.
5753 */
5754 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
5755 int found;
5756
5757 cur = completeWild->nsSet;
5758 prev = NULL;
5759 while (cur != NULL) {
5760 found = 0;
5761 curB = curWild->nsSet;
5762 while (curB != NULL) {
5763 if (cur->value == curB->value) {
5764 found = 1;
5765 break;
5766 }
5767 curB = curB->next;
5768 }
5769 if (!found) {
5770 if (prev == NULL)
5771 completeWild->nsSet = cur->next;
5772 else
5773 prev->next = cur->next;
5774 tmp = cur->next;
5775 xmlFree(cur);
5776 cur = tmp;
5777 continue;
5778 }
5779 prev = cur;
5780 cur = cur->next;
5781 }
5782
5783 return(0);
5784 }
5785 /* 5 If the two are negations of different namespace names,
5786 * then the intersection is not expressible
5787 */
5788 if ((completeWild->negNsSet != NULL) &&
5789 (curWild->negNsSet != NULL) &&
5790 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
5791 (completeWild->negNsSet->value != NULL) &&
5792 (curWild->negNsSet->value != NULL)) {
5793
5794 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
5795 "The intersection of the wilcard is not expressible\n",
5796 NULL, NULL);
5797 return(0);
5798 }
5799 /*
5800 * 6 If the one is a negation of a namespace name and the other
5801 * is a negation of ·absent·, then the one which is the negation
5802 * of a namespace name must be the value.
5803 */
5804 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
5805 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
5806 (completeWild->negNsSet->value == NULL)) {
5807 completeWild->negNsSet->value = curWild->negNsSet->value;
5808 }
5809 return(0);
5810}
5811
5812
5813static xmlSchemaWildcardPtr
5814xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
5815 xmlSchemaAttributePtr attrs,
5816 xmlSchemaWildcardPtr completeWild)
5817{
5818 while (attrs != NULL) {
5819 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5820 xmlSchemaAttributeGroupPtr group;
5821
5822 group = (xmlSchemaAttributeGroupPtr) attrs;
5823 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
5824 if (group->attributes != NULL) {
5825 if (group->attributeWildcard != NULL)
5826 xmlSchemaBuildCompleteAttributeWildcard(ctxt,
5827 group->attributes, group->attributeWildcard);
5828 else
5829 group->attributeWildcard =
5830 xmlSchemaBuildCompleteAttributeWildcard(ctxt,
5831 group->attributes, group->attributeWildcard);
5832 }
5833 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
5834 }
5835 if (group->attributeWildcard != NULL) {
5836 if (completeWild == NULL) {
5837 /*
5838 * Copy the first encountered wildcard as context, except for the annotation.
5839 */
5840 completeWild = xmlSchemaAddWildcard(ctxt);
5841 completeWild->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
5842 if (!xmlSchemaCloneWildcardNsConstraints(ctxt,
5843 &completeWild, group->attributeWildcard))
5844 return(NULL);
5845 completeWild->processContents = group->attributeWildcard->processContents;
5846 /*
5847 * Although the complete wildcard might not correspond to any
5848 * node in the schema, we will save this context node.
5849 */
5850 completeWild->node = group->attributeWildcard->node;
5851 return(completeWild);
5852 }
5853 if (xmlSchemaIntersectWildcards(ctxt, completeWild, group->attributeWildcard) == -1) {
5854 xmlSchemaFreeWildcard(completeWild);
5855 return(NULL);
5856 }
5857 }
5858 }
5859 attrs = attrs->next;
5860 }
5861
5862 return (completeWild);
5863}
5864
5865/**
5866 * xmlSchemaMatchesWildcardNs:
5867 * @wild: the wildcard
5868 * @ns: the namespace
5869 *
5870 *
5871 * Returns 1 if the given namespace matches the wildcard,
5872 * 0 otherwise.
5873 */
5874static int
5875xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
5876{
5877 if (wild == NULL)
5878 return(0);
5879
5880 if (wild->any)
5881 return(1);
5882 else if (wild->nsSet != NULL) {
5883 xmlSchemaWildcardNsPtr cur;
5884
5885 cur = wild->nsSet;
5886 while (cur != NULL) {
5887 if (xmlStrEqual(cur->value, ns))
5888 return(1);
5889 cur = cur->next;
5890 }
5891 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
5892 (!xmlStrEqual(wild->negNsSet->value, ns)))
5893 return(1);
5894
5895 return(0);
5896}
5897
5898/**
5899 * xmlSchemaBuildAttributeValidation:
5900 * @ctxt: the schema parser context
5901 * @type: the complex type definition
5902 *
5903 *
5904 * Builds the wildcard and the attribute uses on the given complex type.
5905 * Returns -1 if an internal error occurs, 0 otherwise.
5906 */
5907static int
5908xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
5909{
5910 xmlSchemaTypePtr baseType = NULL;
5911 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +00005912 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00005913 xmlSchemaAttributePtr attrs;
5914 int baseIsAnyType = 0;
5915
5916 /*
5917 * Complex Type Definition with complex content Schema Component.
5918 *
5919 * Attribute uses.
5920 */
5921 if (type->attributeUses != NULL) {
5922 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5923 "Internal error: xmlSchemaParseBuildAttributeUses: "
5924 "attribute uses already builded.\n",
5925 NULL, NULL);
5926 return (-1);
5927 }
5928 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) ||
5929 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
5930 /*
5931 * Inherit the attribute uses of the base type.
5932 */
5933 baseType = type->subtypes->subtypes->baseType;
5934 /*
5935 * TODO: URGENT: This is not nice, but currently
5936 * xmlSchemaTypeAnyTypeDef is static in xmlschematypes.c.
5937 */
5938 if ((baseType->type == XML_SCHEMA_TYPE_BASIC) &&
William M. Brack803812b2004-06-03 02:11:24 +00005939 xmlStrEqual(baseType->name, BAD_CAST "anyType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005940 baseIsAnyType = 1;
5941 }
5942 /*
5943 * TODO: Does the spec state that it is an error to "extend" the
5944 * anyType?
5945 */
5946 if (!baseIsAnyType) {
5947 if (baseType != NULL) {
5948 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
5949 tmp = (xmlSchemaAttributeLinkPtr)
5950 xmlMalloc(sizeof(xmlSchemaAttributeLink));
5951 if (tmp == NULL) {
5952 xmlSchemaPErrMemory(ctxt,
5953 "building attribute uses of complexType", NULL);
5954 return (-1);
5955 }
5956 tmp->attr = cur->attr;
5957 tmp->next = NULL;
5958 if (type->attributeUses == NULL) {
5959 type->attributeUses = tmp;
5960 } else
5961 lastBaseUse->next = tmp;
5962 lastBaseUse = tmp;
5963 }
5964 }
5965 }
5966 attrs = type->subtypes->subtypes->attributes;
5967 /*
5968 * Handle attribute wildcards.
5969 */
5970 type->attributeWildcard =
5971 xmlSchemaBuildCompleteAttributeWildcard(ctxt,
5972 attrs,
5973 type->subtypes->subtypes->attributeWildcard);
5974 if ((type->attributeWildcard != NULL) &&
5975 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard))
5976 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
5977
5978 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
5979 (baseType != NULL) && (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
5980 (baseType->attributeWildcard != NULL)) {
5981 if (type->attributeWildcard != NULL) {
5982 /*
5983 * Union the complete wildcard with the base wildcard.
5984 */
5985 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
5986 baseType->attributeWildcard) == -1)
5987 return (-1);
5988 } else {
5989 /*
5990 * Just inherit the wildcard.
5991 */
5992 type->attributeWildcard = baseType->attributeWildcard;
5993 }
5994 }
5995 } else {
5996 /*
5997 * Although the complexType is implicitely derived by "restriction"
5998 * from the ur-type, this is not (yet?) reflected by libxml2.
5999 */
6000 baseType = NULL;
6001 attrs = type->attributes;
6002 if (attrs != NULL)
6003 type->attributeWildcard =
6004 xmlSchemaBuildCompleteAttributeWildcard(ctxt, attrs, type->attributeWildcard);
6005 }
6006 /*
6007 * Gather attribute uses defined by this type.
6008 */
6009 if (attrs != NULL) {
6010 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
6011 &uses, &lastUse) == -1) {
6012 return (-1);
6013 }
6014 }
6015 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
6016 * "Two distinct attribute declarations in the {attribute uses} must
6017 * not have identical {name}s and {target namespace}s."
6018 *
6019 * For "extension" this is done further down.
6020 */
6021 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
6022 cur = uses;
6023 while (cur != NULL) {
6024 tmp = cur->next;
6025 while (tmp != NULL) {
6026 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6027 xmlSchemaGetOnymousAttrName(tmp->attr))) &&
6028 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
6029 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
6030
6031 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
6032 "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
6033 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6034 break;
6035 }
6036 tmp = tmp->next;
6037 }
6038 cur = cur->next;
6039 }
6040 }
6041 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
6042 /*
6043 * Derive by restriction.
6044 */
6045 if (baseIsAnyType) {
6046 type->attributeUses = uses;
6047 } else {
6048 int found;
6049
6050 cur = uses;
6051 while (cur != NULL) {
6052 found = 0;
6053 base = type->attributeUses;
6054 while (base != NULL) {
6055 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6056 xmlSchemaGetOnymousAttrName(base->attr))) &&
6057 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr),
6058 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) base->attr)))) {
6059
6060 found = 1;
6061 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6062 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6063 /*
6064 * derivation-ok-restriction 2.1.1
6065 */
6066 xmlSchemaPErr(ctxt, cur->attr->node,
6067 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
6068 "derivation-ok-restriction.2.1.1: "
6069 "The \"optional\" attribute "
6070 "use \"%s\" is inconsistent with a matching "
6071 "\"required\" attribute use of the base type\n",
6072 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6073 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
6074 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6075 /*
6076 * derivation-ok-restriction 3
6077 */
6078 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
6079 "derivation-ok-restriction.3: "
6080 "The \"required\" attribute use \"%s\" of the base type "
6081 "does not have a matching attribute use in the derived type\n",
6082 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6083
6084 } else {
6085 /*
6086 * Override the attribute use.
6087 */
6088 base->attr = cur->attr;
6089 }
6090 /*
6091 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
6092 */
6093 break;
6094 }
6095 base = base->next;
6096 }
6097
6098 if (!found) {
6099 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6100 /*
6101 * derivation-ok-restriction 2.2
6102 */
6103 if ((type->attributeWildcard != NULL) &&
6104 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
6105 cur->attr->targetNamespace))
6106 found = 1;
6107
6108 if (!found) {
6109 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
6110 "derivation-ok-restriction.2.2: "
6111 "The attribute use \"%s\" has neither a matching attribute use, "
6112 "nor a matching wildcard in the base type\n",
6113 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6114 } else {
6115 /*
6116 * Add the attribute use.
6117 *
6118 * Note that this may lead to funny derivation error reports, if
6119 * multiple equal attribute uses exist; but this is not
6120 * allowed anyway, and it will be reported beforehand.
6121 */
6122 tmp = cur;
6123 if (prev != NULL)
6124 prev->next = cur->next;
6125 else
6126 uses = cur->next;
6127 cur = cur->next;
6128 if (type->attributeUses == NULL) {
6129 type->attributeUses = tmp;
6130 } else
6131 lastBaseUse->next = tmp;
6132 lastBaseUse = tmp;
6133
6134 continue;
6135 }
6136 }
6137 }
6138 prev = cur;
6139 cur = cur->next;
6140 }
6141 if (uses != NULL)
6142 xmlSchemaFreeAttributeUseList(uses);
6143 }
6144 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
6145 /*
6146 * The spec allows only appending, and not other kinds of extensions.
6147 *
6148 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
6149 */
6150 if (uses != NULL) {
6151 if (type->attributeUses == NULL) {
6152 type->attributeUses = uses;
6153 } else
6154 lastBaseUse->next = uses;
6155 }
6156 } else {
6157 /*
6158 * Derive implicitely from the ur-type.
6159 */
6160 type->attributeUses = uses;
6161}
6162 /*
6163 * 3.4.6 -> Complex Type Definition Properties Correct
6164 */
6165 if (type->attributeUses != NULL) {
6166 cur = type->attributeUses;
6167 prev = NULL;
6168 while (cur != NULL) {
6169 /*
6170 * 4. Two distinct attribute declarations in the {attribute uses} must
6171 * not have identical {name}s and {target namespace}s.
6172 *
6173 * Note that this was already done for "restriction" and types derived from
6174 * the ur-type.
6175 */
6176 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
6177 tmp = cur->next;
6178 while (tmp != NULL) {
6179 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6180 xmlSchemaGetOnymousAttrName(tmp->attr))) &&
6181 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
6182 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
6183
6184 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
6185 "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
6186 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6187 break;
6188 }
6189 tmp = tmp->next;
6190 }
6191 }
6192 /*
6193 * 5. Two distinct attribute declarations in the {attribute uses} must
6194 * not have {type definition}s which are or are derived from ID.
6195 */
6196 if ((cur->attr->subtypes != NULL) &&
6197 /*
6198 * TODO: FIXME: XML_SCHEMAS_ID should be used instead of "23" !!!,
6199 * but the xmlSchemaValType is not made public yet.
6200 */
6201 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, 23))) {
6202 if (id != NULL) {
6203 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_5,
6204 "ct-props-correct.5: Two attribute declarations, "
6205 "\"%s\" and \"%s\" have types which derived from ID\n",
6206 xmlSchemaGetOnymousAttrName(id->attr),
6207 xmlSchemaGetOnymousAttrName(cur->attr));
6208 }
6209 id = cur;
6210 }
6211 /*
6212 * Remove "prohibited" attribute uses. The reason this is done at this late
6213 * stage is to be able to catch dublicate attribute uses. So we had to keep
6214 * prohibited uses in the list as well.
6215 */
6216 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6217 tmp = cur;
6218 if (prev == NULL)
6219 type->attributeUses = cur->next;
6220 else
6221 prev->next = cur->next;
6222 cur = cur->next;
6223 xmlFree(tmp);
6224 } else {
6225 prev = cur;
6226 cur = cur->next;
6227 }
6228 }
6229 }
6230 /*
6231 * TODO: This check should be removed if we are 100% sure of
6232 * the base type attribute uses already being built.
6233 */
6234 if ((baseType != NULL) && (!baseIsAnyType) &&
6235 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
6236 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
6237 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAS_ERR_INTERNAL,
6238 "Internal error: xmlSchemaParseBuildAttributeUses: "
6239 "attribute uses not builded on base type \"%s\".\n",
6240 baseType->name, NULL);
6241 }
6242 return (0);
6243}
6244
6245/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006246 * xmlSchemaTypeFixup:
6247 * @typeDecl: the schema type definition
6248 * @ctxt: the schema parser context
6249 *
6250 * Fixes the content model of the type.
6251 */
6252static void
6253xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006254 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00006255{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006256 if (typeDecl == NULL)
6257 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006258 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006259 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006260 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006261 switch (typeDecl->type) {
6262 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
6263 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
6264 if (typeDecl->subtypes != NULL)
6265 typeDecl->contentType =
6266 typeDecl->subtypes->contentType;
6267 break;
6268 }
6269 case XML_SCHEMA_TYPE_RESTRICTION:{
6270 if (typeDecl->subtypes != NULL)
6271 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006272
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006273 if (typeDecl->base != NULL) {
6274 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00006275
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006276 baseType =
6277 xmlSchemaGetType(ctxt->schema, typeDecl->base,
6278 typeDecl->baseNs);
6279 if (baseType == NULL) {
6280 xmlSchemaPErr(ctxt, typeDecl->node,
6281 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00006282 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006283 name, typeDecl->base);
Daniel Veillard3646d642004-06-02 19:19:14 +00006284 } else if (baseType->contentType ==
6285 XML_SCHEMA_CONTENT_UNKNOWN) {
6286 /*
6287 * The base type might be not "type fixed" yet,
6288 * so do it now. */
6289 /*
6290 * TODO: Is a check for circular derivation already
6291 * done?
6292 */
6293 xmlSchemaTypeFixup(baseType, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006294 }
6295 typeDecl->baseType = baseType;
6296 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006297 if (typeDecl->subtypes == NULL)
William M. Bracke7091952004-05-11 15:09:58 +00006298 if (typeDecl->baseType != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006299 typeDecl->contentType =
6300 typeDecl->baseType->contentType;
William M. Bracke7091952004-05-11 15:09:58 +00006301 } else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006302 /* 1.1.1 */
6303 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006304 else if ((typeDecl->subtypes->subtypes == NULL) &&
6305 ((typeDecl->subtypes->type ==
6306 XML_SCHEMA_TYPE_ALL)
6307 || (typeDecl->subtypes->type ==
6308 XML_SCHEMA_TYPE_SEQUENCE)))
6309 /* 1.1.2 */
6310 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
6311 else if ((typeDecl->subtypes->type ==
6312 XML_SCHEMA_TYPE_CHOICE)
6313 && (typeDecl->subtypes->subtypes == NULL))
6314 /* 1.1.3 */
6315 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
6316 else {
6317 /* 1.2 and 2.X are applied at the other layer */
6318 typeDecl->contentType =
6319 XML_SCHEMA_CONTENT_ELEMENTS;
6320 }
6321 break;
6322 }
6323 case XML_SCHEMA_TYPE_EXTENSION:{
6324 xmlSchemaContentType explicitContentType;
6325 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00006326
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006327 if (typeDecl->base != NULL) {
6328 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00006329
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006330 baseType =
6331 xmlSchemaGetType(ctxt->schema, typeDecl->base,
6332 typeDecl->baseNs);
6333 if (baseType == NULL) {
6334 xmlSchemaPErr(ctxt, typeDecl->node,
6335 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00006336 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006337 name, typeDecl->base);
Daniel Veillard3646d642004-06-02 19:19:14 +00006338 } else if (baseType->contentType ==
6339 XML_SCHEMA_CONTENT_UNKNOWN) {
6340 /*
6341 * The base type might be not "type fixed" yet,
6342 * so do it now. */
6343 /*
6344 * TODO: Is a check for circular derivation already
6345 * done?
6346 */
6347 xmlSchemaTypeFixup(baseType, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006348 }
6349 typeDecl->baseType = baseType;
6350 }
6351 if (typeDecl->subtypes != NULL)
6352 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006353
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006354 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
6355 if (typeDecl->subtypes == NULL)
6356 /* 1.1.1 */
6357 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
6358 else if ((typeDecl->subtypes->subtypes == NULL) &&
6359 ((typeDecl->subtypes->type ==
6360 XML_SCHEMA_TYPE_ALL)
6361 || (typeDecl->subtypes->type ==
6362 XML_SCHEMA_TYPE_SEQUENCE)))
6363 /* 1.1.2 */
6364 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
6365 else if ((typeDecl->subtypes->type ==
6366 XML_SCHEMA_TYPE_CHOICE)
6367 && (typeDecl->subtypes->subtypes == NULL))
6368 /* 1.1.3 */
6369 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00006370
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006371 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
6372 typeDecl->baseNs);
6373 if (base == NULL) {
6374 xmlSchemaPErr(ctxt, typeDecl->node,
6375 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
6376 "Schemas: base type %s of type %s not found\n",
6377 typeDecl->base, name);
6378 return;
6379 }
Daniel Veillard2582a332004-04-18 19:49:46 +00006380 if (typeDecl->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006381 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillard2582a332004-04-18 19:49:46 +00006382 xmlSchemaPErr(ctxt, typeDecl->node,
6383 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
6384 "Schemas: extension type %s is recursive\n",
6385 name, NULL);
6386 return;
6387 }
6388 typeDecl->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006389 xmlSchemaTypeFixup(base, ctxt, NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +00006390 typeDecl->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006391 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
6392 /* 2.1 */
6393 typeDecl->contentType = base->contentType;
6394 } else if (base->contentType ==
6395 XML_SCHEMA_CONTENT_EMPTY) {
6396 /* 2.2 imbitable ! */
6397 typeDecl->contentType =
6398 XML_SCHEMA_CONTENT_ELEMENTS;
6399 } else {
6400 /* 2.3 imbitable pareil ! */
6401 typeDecl->contentType =
6402 XML_SCHEMA_CONTENT_ELEMENTS;
6403 }
6404 break;
6405 }
6406 case XML_SCHEMA_TYPE_COMPLEX:{
6407 if (typeDecl->subtypes == NULL) {
6408 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00006409
6410 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
6411 typeDecl->contentType =
6412 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006413 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00006414 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006415 typeDecl->contentType =
6416 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +00006417 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006418 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
6419 NULL);
6420 if (typeDecl->subtypes != NULL)
6421 typeDecl->contentType =
6422 typeDecl->subtypes->contentType;
6423 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006424 /* Evaluate the derivation method. */
6425 if ((typeDecl->subtypes != NULL) &&
6426 ((typeDecl->subtypes->type ==
6427 XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
6428 (typeDecl->subtypes->type ==
6429 XML_SCHEMA_TYPE_SIMPLE_CONTENT)) &&
6430 (typeDecl->subtypes->subtypes != NULL)) {
6431 if (typeDecl->subtypes->subtypes->type ==
6432 XML_SCHEMA_TYPE_EXTENSION) {
6433 typeDecl->flags |=
6434 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
6435 } else if (typeDecl->subtypes->subtypes->type ==
6436 XML_SCHEMA_TYPE_RESTRICTION) {
6437 typeDecl->flags |=
6438 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006439 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006440 }
6441 }
6442 xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006443 break;
6444 }
6445 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
6446 if (typeDecl->subtypes == NULL) {
6447 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00006448 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
6449 typeDecl->contentType =
6450 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006451 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00006452 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006453 typeDecl->contentType =
6454 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +00006455 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006456 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
6457 NULL);
6458 if (typeDecl->subtypes != NULL)
6459 typeDecl->contentType =
6460 typeDecl->subtypes->contentType;
6461 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006462 /*
6463 * Removed due to implementation of the build of attribute uses.
6464 */
6465 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00006466 if (typeDecl->attributes == NULL)
6467 typeDecl->attributes =
6468 typeDecl->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +00006469 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006470 }
6471 break;
6472 }
6473 case XML_SCHEMA_TYPE_SEQUENCE:
6474 case XML_SCHEMA_TYPE_GROUP:
6475 case XML_SCHEMA_TYPE_ALL:
6476 case XML_SCHEMA_TYPE_CHOICE:
6477 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
6478 break;
Daniel Veillard3646d642004-06-02 19:19:14 +00006479 case XML_SCHEMA_TYPE_LIST:
6480 xmlSchemaParseListRefFixup(typeDecl, ctxt);
6481 /* no break on purpose */
6482 case XML_SCHEMA_TYPE_UNION:
6483 if (typeDecl->type == XML_SCHEMA_TYPE_UNION)
6484 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
6485 /* no break on purpose */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006486 case XML_SCHEMA_TYPE_BASIC:
6487 case XML_SCHEMA_TYPE_ANY:
6488 case XML_SCHEMA_TYPE_FACET:
6489 case XML_SCHEMA_TYPE_SIMPLE:
6490 case XML_SCHEMA_TYPE_UR:
6491 case XML_SCHEMA_TYPE_ELEMENT:
6492 case XML_SCHEMA_TYPE_ATTRIBUTE:
6493 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +00006494 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006495 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006496 case XML_SCHEMA_FACET_MININCLUSIVE:
6497 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6498 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6499 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
6500 case XML_SCHEMA_FACET_TOTALDIGITS:
6501 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6502 case XML_SCHEMA_FACET_PATTERN:
6503 case XML_SCHEMA_FACET_ENUMERATION:
6504 case XML_SCHEMA_FACET_WHITESPACE:
6505 case XML_SCHEMA_FACET_LENGTH:
6506 case XML_SCHEMA_FACET_MAXLENGTH:
6507 case XML_SCHEMA_FACET_MINLENGTH:
6508 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006509 if (typeDecl->subtypes != NULL)
6510 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006511 break;
6512 }
6513 }
Daniel Veillard8651f532002-04-17 09:06:27 +00006514#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006515 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006516 xmlGenericError(xmlGenericErrorContext,
6517 "Type of %s : %s:%d :", name,
6518 typeDecl->node->doc->URL,
6519 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006520 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006521 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006522 }
Daniel Veillard8651f532002-04-17 09:06:27 +00006523 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006524 case XML_SCHEMA_CONTENT_SIMPLE:
6525 xmlGenericError(xmlGenericErrorContext, "simple\n");
6526 break;
6527 case XML_SCHEMA_CONTENT_ELEMENTS:
6528 xmlGenericError(xmlGenericErrorContext, "elements\n");
6529 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006530 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006531 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
6532 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006533 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006534 xmlGenericError(xmlGenericErrorContext, "empty\n");
6535 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006536 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006537 xmlGenericError(xmlGenericErrorContext, "mixed\n");
6538 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006539 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006540 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
6541 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006542 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006543 xmlGenericError(xmlGenericErrorContext, "basic\n");
6544 break;
6545 default:
6546 xmlGenericError(xmlGenericErrorContext,
6547 "not registered !!!\n");
6548 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00006549 }
6550#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00006551}
6552
6553/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006554 * xmlSchemaCheckFacet:
6555 * @facet: the facet
6556 * @typeDecl: the schema type definition
6557 * @ctxt: the schema parser context or NULL
6558 * @name: name of the type
6559 *
6560 * Checks the default values types, especially for facets
6561 *
6562 * Returns 0 if okay or -1 in cae of error
6563 */
6564int
6565xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006566 xmlSchemaTypePtr typeDecl,
6567 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006568{
6569 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
6570 int ret = 0;
6571
6572 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006573 nonNegativeIntegerType =
6574 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
6575 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006576 }
6577 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006578 case XML_SCHEMA_FACET_MININCLUSIVE:
6579 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6580 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6581 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
6582 /*
6583 * Okay we need to validate the value
6584 * at that point.
6585 */
6586 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006587
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006588 vctxt = xmlSchemaNewValidCtxt(NULL);
6589 if (vctxt == NULL)
6590 break;
6591 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
6592 facet->value);
6593 facet->val = vctxt->value;
6594 vctxt->value = NULL;
6595 if (facet->val == NULL) {
6596 /* error code */
6597 if (ctxt != NULL) {
6598 xmlSchemaPErr(ctxt, facet->node,
6599 XML_SCHEMAP_INVALID_FACET,
6600 "Schemas: type %s facet value %s invalid\n",
6601 name, facet->value);
6602 }
6603 ret = -1;
6604 }
6605 xmlSchemaFreeValidCtxt(vctxt);
6606 break;
6607 }
6608 case XML_SCHEMA_FACET_ENUMERATION:{
6609 /*
6610 * Okay we need to validate the value
6611 * at that point.
6612 */
6613 xmlSchemaValidCtxtPtr vctxt;
6614 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006615
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006616 vctxt = xmlSchemaNewValidCtxt(NULL);
6617 if (vctxt == NULL)
6618 break;
6619 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
6620 facet->value);
6621 if (tmp != 0) {
6622 if (ctxt != NULL) {
6623 xmlSchemaPErr(ctxt, facet->node,
6624 XML_SCHEMAP_INVALID_ENUM,
6625 "Schemas: type %s enumeration value %s invalid\n",
6626 name, facet->value);
6627 }
6628 ret = -1;
6629 }
6630 xmlSchemaFreeValidCtxt(vctxt);
6631 break;
6632 }
6633 case XML_SCHEMA_FACET_PATTERN:
6634 facet->regexp = xmlRegexpCompile(facet->value);
6635 if (facet->regexp == NULL) {
6636 xmlSchemaPErr(ctxt, typeDecl->node,
6637 XML_SCHEMAP_REGEXP_INVALID,
6638 "Schemas: type %s facet regexp %s invalid\n",
6639 name, facet->value);
6640 ret = -1;
6641 }
6642 break;
6643 case XML_SCHEMA_FACET_TOTALDIGITS:
6644 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6645 case XML_SCHEMA_FACET_LENGTH:
6646 case XML_SCHEMA_FACET_MAXLENGTH:
6647 case XML_SCHEMA_FACET_MINLENGTH:{
6648 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006649
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006650 tmp =
6651 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
6652 facet->value,
6653 &facet->val);
6654 if (tmp != 0) {
6655 /* error code */
6656 if (ctxt != NULL) {
6657 xmlSchemaPErr(ctxt, facet->node,
6658 XML_SCHEMAP_INVALID_FACET_VALUE,
6659 "Schemas: type %s facet value %s invalid\n",
6660 name, facet->value);
6661 }
6662 ret = -1;
6663 }
6664 break;
6665 }
6666 case XML_SCHEMA_FACET_WHITESPACE:{
6667 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
6668 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
6669 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
6670 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
6671 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
6672 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
6673 } else {
6674 if (ctxt != NULL) {
6675 xmlSchemaPErr(ctxt, facet->node,
6676 XML_SCHEMAP_INVALID_WHITE_SPACE,
6677 "Schemas: type %s whiteSpace value %s invalid\n",
6678 name, facet->value);
6679 }
6680 ret = -1;
6681 }
6682 }
6683 default:
6684 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006685 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006686 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006687}
6688
6689/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006690 * xmlSchemaCheckDefaults:
6691 * @typeDecl: the schema type definition
6692 * @ctxt: the schema parser context
6693 *
6694 * Checks the default values types, especially for facets
6695 */
6696static void
6697xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006698 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00006699{
Daniel Veillard4255d502002-04-16 15:50:10 +00006700 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006701 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006702 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006703 if (typeDecl->facets != NULL) {
6704 xmlSchemaFacetPtr facet = typeDecl->facets;
6705
6706 while (facet != NULL) {
6707 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
6708 facet = facet->next;
6709 }
6710 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006711 }
6712}
6713
6714/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00006715 * xmlSchemaAttrGrpFixup:
6716 * @attrgrpDecl: the schema attribute definition
6717 * @ctxt: the schema parser context
6718 * @name: the attribute name
6719 *
6720 * Fixes finish doing the computations on the attributes definitions
6721 */
6722static void
Daniel Veillard3646d642004-06-02 19:19:14 +00006723xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006724 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00006725{
6726 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00006727 name = attrgrp->name;
6728 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006729 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00006730 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006731 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006732
Daniel Veillard3646d642004-06-02 19:19:14 +00006733 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref, attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006734 if (ref == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006735 xmlSchemaPErr(ctxt, attrgrp->node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006736 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
6737 "Schemas: attribute group %s reference %s not found\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00006738 name, attrgrp->ref);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006739 return;
6740 }
6741 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00006742 attrgrp->attributes = ref->attributes;
6743 attrgrp->attributeWildcard = ref->attributeWildcard;
6744 }
6745 /*
6746 * Removed, since a global attribute group does not need to hold any
6747 * attributes or wildcard
6748 */
6749 /*
6750 else {
6751 xmlSchemaPErr(ctxt, attrgrp->node, XML_SCHEMAP_NOATTR_NOREF,
6752 "Schemas: attribute group %s has no attributes nor reference\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006753 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00006754 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006755 */
Daniel Veillard13e04c62002-04-23 17:51:29 +00006756}
6757
6758/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006759 * xmlSchemaAttrFixup:
6760 * @attrDecl: the schema attribute definition
6761 * @ctxt: the schema parser context
6762 * @name: the attribute name
6763 *
6764 * Fixes finish doing the computations on the attributes definitions
6765 */
6766static void
6767xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006768 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00006769{
6770 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006771 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006772 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006773 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006774 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006775 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006776
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006777 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
6778 attrDecl->typeNs);
6779 if (type == NULL) {
6780 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
6781 "Schemas: attribute %s type %s not found\n",
6782 name, attrDecl->typeName);
6783 }
6784 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006785 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006786 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00006787
Daniel Veillard3646d642004-06-02 19:19:14 +00006788 ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006789 if (ref == NULL) {
6790 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
6791 "Schemas: attribute %s reference %s not found\n",
6792 name, attrDecl->ref);
6793 return;
6794 }
6795 xmlSchemaAttrFixup(ref, ctxt, NULL);
6796 attrDecl->subtypes = ref->subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +00006797 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006798 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
6799 "Schemas: attribute %s has no type nor reference\n",
6800 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006801 }
6802}
6803
6804/**
6805 * xmlSchemaParse:
6806 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00006807 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00006808 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00006809 * XML Shema struture which can be used to validate instances.
6810 * *WARNING* this interface is highly subject to change
6811 *
6812 * Returns the internal XML Schema structure built from the resource or
6813 * NULL in case of error
6814 */
6815xmlSchemaPtr
6816xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
6817{
6818 xmlSchemaPtr ret = NULL;
6819 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006820 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00006821 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00006822 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006823
6824 xmlSchemaInitTypes();
6825
Daniel Veillard6045c902002-10-09 21:13:59 +00006826 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00006827 return (NULL);
6828
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00006829 nberrors = ctxt->nberrors;
6830 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006831 ctxt->counter = 0;
6832 ctxt->container = NULL;
6833
6834 /*
6835 * First step is to parse the input document into an DOM/Infoset
6836 */
Daniel Veillard6045c902002-10-09 21:13:59 +00006837 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006838 doc = xmlReadFile((const char *) ctxt->URL, NULL,
6839 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006840 if (doc == NULL) {
6841 xmlSchemaPErr(ctxt, NULL,
6842 XML_SCHEMAP_FAILED_LOAD,
6843 "xmlSchemaParse: could not load %s\n",
6844 ctxt->URL, NULL);
6845 return (NULL);
6846 }
Daniel Veillard6045c902002-10-09 21:13:59 +00006847 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006848 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
6849 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006850 if (doc == NULL) {
6851 xmlSchemaPErr(ctxt, NULL,
6852 XML_SCHEMAP_FAILED_PARSE,
6853 "xmlSchemaParse: could not parse\n",
6854 NULL, NULL);
6855 return (NULL);
6856 }
6857 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00006858 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00006859 } else if (ctxt->doc != NULL) {
6860 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00006861 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00006862 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006863 xmlSchemaPErr(ctxt, NULL,
6864 XML_SCHEMAP_NOTHING_TO_PARSE,
6865 "xmlSchemaParse: could not parse\n",
6866 NULL, NULL);
6867 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006868 }
6869
6870 /*
6871 * Then extract the root and Schema parse it
6872 */
6873 root = xmlDocGetRootElement(doc);
6874 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006875 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
6876 XML_SCHEMAP_NOROOT,
6877 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00006878 if (!preserve) {
6879 xmlFreeDoc(doc);
6880 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006881 return (NULL);
6882 }
6883
6884 /*
6885 * Remove all the blank text nodes
6886 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006887 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00006888
6889 /*
6890 * Then do the parsing for good
6891 */
6892 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00006893 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00006894 if (!preserve) {
6895 xmlFreeDoc(doc);
6896 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006897 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00006898 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006899 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00006900 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00006901
6902 /*
6903 * Then fix all the references.
6904 */
6905 ctxt->schema = ret;
6906 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006907 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006908
6909 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00006910 * Then fixup all attributes declarations
6911 */
6912 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
6913
6914 /*
6915 * Then fixup all attributes group declarations
6916 */
6917 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
6918 ctxt);
6919
6920 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00006921 * Then fixup all types properties
6922 */
6923 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
6924
6925 /*
6926 * Then build the content model for all elements
6927 */
6928 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006929 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006930
6931 /*
6932 * Then check the defaults part of the type like facets values
6933 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006934 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
6935 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006936
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00006937 if (ctxt->nberrors != 0) {
6938 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006939 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00006940 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006941 return (ret);
6942}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006943
Daniel Veillard4255d502002-04-16 15:50:10 +00006944/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00006945 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00006946 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00006947 * @err: the error callback
6948 * @warn: the warning callback
6949 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00006950 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00006951 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00006952 */
6953void
6954xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006955 xmlSchemaValidityErrorFunc err,
6956 xmlSchemaValidityWarningFunc warn, void *ctx)
6957{
Daniel Veillard4255d502002-04-16 15:50:10 +00006958 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006959 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006960 ctxt->error = err;
6961 ctxt->warning = warn;
6962 ctxt->userData = ctx;
6963}
6964
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006965/**
6966 * xmlSchemaFacetTypeToString:
6967 * @type: the facet type
6968 *
6969 * Convert the xmlSchemaTypeType to a char string.
6970 *
6971 * Returns the char string representation of the facet type if the
6972 * type is a facet and an "Internal Error" string otherwise.
6973 */
6974static const char *
6975xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
6976{
6977 switch (type) {
6978 case XML_SCHEMA_FACET_PATTERN:
6979 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006980 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006981 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006982 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006983 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006984 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006985 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006986 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006987 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006988 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006989 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006990 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006991 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006992 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006993 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006994 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006995 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006996 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006997 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006998 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00006999 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007000 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007001 return ("fractionDigits");
7002 default:
7003 break;
7004 }
7005 return ("Internal Error");
7006}
7007
7008/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00007009 * xmlSchemaValidateFacetsInternal:
7010 * @ctxt: a schema validation context
7011 * @base: the base type
7012 * @facets: the list of facets to check
7013 * @value: the lexical repr of the value to validate
7014 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +00007015 * @fireErrors: if 0, only internal errors will be fired;
7016 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00007017 *
7018 * Check a value against all facet conditions
7019 *
7020 * Returns 0 if the element is schemas valid, a positive error code
7021 * number otherwise and -1 in case of internal or API error.
7022 */
7023static int
7024xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
7025 xmlSchemaTypePtr base,
William M. Bracke7091952004-05-11 15:09:58 +00007026 xmlSchemaFacetPtr facets,
7027 const xmlChar * value, int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00007028{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007029 int ret = 0;
7030 int tmp = 0;
7031 xmlSchemaTypeType type;
7032 xmlSchemaFacetPtr facet = facets;
7033
7034 while (facet != NULL) {
7035 type = facet->type;
7036 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007037 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007038
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007039 while (facet != NULL) {
7040 tmp =
7041 xmlSchemaValidateFacet(base, facet, value,
7042 ctxt->value);
7043 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007044 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007045 }
7046 facet = facet->next;
7047 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007048 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007049 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007050
7051 if (tmp != 0) {
7052 ret = tmp;
Daniel Veillard377e1a92004-04-16 16:30:05 +00007053 if (fireErrors)
William M. Bracke7091952004-05-11 15:09:58 +00007054 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET,
7055 "Failed to validate type with facet %s\n",
7056 (const xmlChar *) xmlSchemaFacetTypeToString(type),
7057 NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007058 }
7059 if (facet != NULL)
7060 facet = facet->next;
7061 }
7062 return (ret);
7063}
7064
William M. Brack87640d52004-04-17 14:58:15 +00007065/**
7066 * xmlSchemaValidateFacets:
7067 * @ctxt: a schema validation context
7068 * @base: the base type
7069 * @facets: the list of facets to check
7070 * @value: the lexical repr of the value to validate
7071 * @val: the precomputed value
7072 *
7073 * Check a value against all facet conditions
7074 *
7075 * Returns 0 if the element is schemas valid, a positive error code
7076 * number otherwise and -1 in case of internal or API error.
7077 */
7078static int
7079xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
7080 xmlSchemaTypePtr base,
7081 xmlSchemaFacetPtr facets, const xmlChar * value)
7082{
7083 return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
7084}
7085
Daniel Veillard4255d502002-04-16 15:50:10 +00007086/************************************************************************
7087 * *
7088 * Simple type validation *
7089 * *
7090 ************************************************************************/
7091
7092/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00007093 * xmlSchemaValidateSimpleValueUnion:
7094 * @ctxt: a schema validation context
7095 * @type: the type declaration
7096 * @value: the value to validate
7097 *
7098 * Validates a value against a union.
7099 *
7100 * Returns 0 if the value is valid, a positive error code
7101 * number otherwise and -1 in case of internal or API error.
7102 */
7103static int
7104xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
7105 xmlSchemaTypePtr type, const xmlChar * value)
7106{
7107 int ret = 0;
7108 const xmlChar *cur, *end, *prefix, *ncName;
7109 xmlChar *tmp;
7110 xmlSchemaTypePtr subtype;
7111 xmlNsPtr ns;
7112 int len;
7113
7114
7115 /* Process referenced memberTypes. */
7116 cur = type->ref;
7117 do {
7118 while (IS_BLANK_CH(*cur))
7119 cur++;
7120 end = cur;
7121 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7122 end++;
7123 if (end == cur)
7124 break;
7125 tmp = xmlStrndup(cur, end - cur);
7126 ncName = xmlSplitQName3(tmp, &len);
7127 if (ncName != NULL) {
7128 prefix = xmlStrndup(tmp, len);
7129 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
7130 } else {
7131 prefix = NULL;
7132 ncName = tmp;
7133 }
William M. Bracke7091952004-05-11 15:09:58 +00007134 /* We won't do additional checks here,
7135 * since they have been performed during parsing. */
Daniel Veillard377e1a92004-04-16 16:30:05 +00007136 ns = xmlSearchNs(type->node->doc, type->node, prefix);
7137 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
7138 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
7139 if (tmp != NULL)
7140 xmlFree(tmp);
7141 if (prefix != NULL)
William M. Brack87640d52004-04-17 14:58:15 +00007142 xmlFree((void *)prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007143 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
7144 if ((ret == 0) || (ret == -1)) {
7145 return (ret);
7146 }
7147 cur = end;
7148 } while (*cur != 0);
7149
7150 if (type->subtypes != NULL) {
7151 subtype = type->subtypes;
7152 do {
7153 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
7154 if ((ret == 0) || (ret == -1)) {
7155 return (ret);
7156 }
7157 subtype = subtype->next;
7158 } while (subtype != NULL);
7159 }
7160 return (ret);
7161}
7162
7163/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007164 * xmlSchemaValidateSimpleValue:
7165 * @ctxt: a schema validation context
7166 * @type: the type declaration
7167 * @value: the value to validate
7168 *
7169 * Validate a value against a simple type
7170 *
7171 * Returns 0 if the value is valid, a positive error code
7172 * number otherwise and -1 in case of internal or API error.
7173 */
7174static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007175xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007176 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007177{
Daniel Veillard377e1a92004-04-16 16:30:05 +00007178 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
7179}
7180
7181/**
7182 * xmlSchemaValidateSimpleValue:
7183 * @ctxt: a schema validation context
7184 * @type: the type declaration
7185 * @value: the value to validate
William M. Bracke7091952004-05-11 15:09:58 +00007186 * @fireErrors: if 0, only internal errors will be fired;
7187 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00007188 *
7189 * Validate a value against a simple type
7190 *
7191 * Returns 0 if the value is valid, a positive error code
7192 * number otherwise and -1 in case of internal or API error.
7193 */
7194static int
7195xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
William M. Bracke7091952004-05-11 15:09:58 +00007196 xmlSchemaTypePtr type,
7197 const xmlChar * value,
7198 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00007199{
Daniel Veillard4255d502002-04-16 15:50:10 +00007200 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007201
Daniel Veillard4255d502002-04-16 15:50:10 +00007202 /*
7203 * First normalize the value accordingly to Schema Datatype
7204 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
William M. Bracke7091952004-05-11 15:09:58 +00007205 *
Daniel Veillard4255d502002-04-16 15:50:10 +00007206 * Then check the normalized value against the lexical space of the
7207 * type.
7208 */
7209 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007210 if (ctxt->value != NULL) {
7211 xmlSchemaFreeValue(ctxt->value);
7212 ctxt->value = NULL;
7213 }
7214 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
7215 ctxt->cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007216 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00007217 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
7218 "Failed to validate basic type %s\n",
7219 type->name, NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007220 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007221 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007222 xmlSchemaTypePtr base;
7223 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00007224
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007225 base = type->baseType;
7226 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00007227 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
7228 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007229 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007230 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007231 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007232
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007233 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00007234 * Do not validate facets or attributes when working on
7235 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007236 */
7237 if (ctxt->schema != NULL) {
7238 if (ret == 0) {
7239 facet = type->facets;
William M. Bracke7091952004-05-11 15:09:58 +00007240 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet,
7241 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007242 }
7243 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007244 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007245 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00007246
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007247 base = type->subtypes;
7248 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00007249 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
7250 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007251 } else {
7252 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00007253 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007254 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007255 const xmlChar *cur, *end;
7256 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007257 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00007258
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007259 base = type->subtypes;
7260 if (base == NULL) {
7261 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
7262 "Internal: List type %s has no base type\n",
7263 type->name, NULL);
7264 return (-1);
7265 }
7266 cur = value;
7267 do {
William M. Brack76e95df2003-10-18 16:20:14 +00007268 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007269 cur++;
7270 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00007271 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007272 end++;
7273 if (end == cur)
7274 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007275 tmp = xmlStrndup(cur, end - cur);
William M. Bracke7091952004-05-11 15:09:58 +00007276 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base,
7277 tmp, fireErrors);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007278 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007279 if (ret2 != 0)
7280 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007281 cur = end;
7282 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007283 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
7284 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
7285 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00007286 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
7287 "Failed to validate type %s\n", type->name, NULL);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007288 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007289 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007290 TODO
7291 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007292 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007293}
7294
7295/************************************************************************
7296 * *
7297 * DOM Validation code *
7298 * *
7299 ************************************************************************/
7300
7301static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007302 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007303static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007304 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +00007305 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007306static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007307 xmlNodePtr elem,
7308 xmlSchemaElementPtr elemDecl,
7309 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007310
Daniel Veillard3646d642004-06-02 19:19:14 +00007311
7312/**
7313 * xmlSchemaFreeAttrStates:
7314 * @state: a list of attribute states
7315 *
7316 * Free the given list of attribute states
7317 *
7318 */
7319static void
7320xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
7321{
7322 xmlSchemaAttrStatePtr tmp;
7323 while (state != NULL) {
7324 tmp = state;
7325 state = state->next;
7326 xmlFree(tmp);
7327 }
7328}
7329
Daniel Veillard4255d502002-04-16 15:50:10 +00007330/**
7331 * xmlSchemaRegisterAttributes:
7332 * @ctxt: a schema validation context
7333 * @attrs: a list of attributes
7334 *
7335 * Register the list of attributes as the set to be validated on that element
7336 *
7337 * Returns -1 in case of error, 0 otherwise
7338 */
7339static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007340xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
7341{
Daniel Veillard3646d642004-06-02 19:19:14 +00007342 xmlSchemaAttrStatePtr tmp;
7343
7344 ctxt->attr = NULL;
7345 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007346 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007347 if ((attrs->ns != NULL) &&
7348 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
7349 attrs = attrs->next;
7350 continue;
7351 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007352 tmp = (xmlSchemaAttrStatePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00007353 xmlMalloc(sizeof(xmlSchemaAttrState));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007354 if (tmp == NULL) {
7355 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007356 return (-1);
7357 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007358 tmp->attr = attrs;
7359 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
7360 tmp->next = NULL;
7361 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007362 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00007363 else
7364 ctxt->attrTop->next = tmp;
7365 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007366 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007367 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007368 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007369}
7370
7371/**
7372 * xmlSchemaCheckAttributes:
7373 * @ctxt: a schema validation context
7374 * @node: the node carrying it.
7375 *
7376 * Check that the registered set of attributes on the current node
7377 * has been properly validated.
7378 *
7379 * Returns 0 if validity constraints are met, 1 otherwise.
7380 */
7381static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007382xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7383{
Daniel Veillard4255d502002-04-16 15:50:10 +00007384 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00007385 xmlSchemaAttrStatePtr cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00007386
Daniel Veillard3646d642004-06-02 19:19:14 +00007387 cur = ctxt->attr;
7388 while ((cur != NULL) && (cur != ctxt->attrTop->next)) {
7389 if (cur->state != XML_SCHEMAS_ATTR_CHECKED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007390 ret = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00007391 if (cur->state == XML_SCHEMAS_ATTR_UNKNOWN)
William M. Bracke7091952004-05-11 15:09:58 +00007392 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
7393 "Attribute %s on %s is unknown\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00007394 cur->attr->name, node->name);
7395 else if (cur->state == XML_SCHEMAS_ATTR_PROHIBITED)
7396 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
7397 "Attribute %s on %s is prohibited\n",
7398 cur->attr->name, node->name);
7399 else if (cur->state == XML_SCHEMAS_ATTR_INVALID_VALUE)
7400 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRINVALID,
7401 "Attribute %s on %s does not match type\n",
7402 cur->attr->name, node->name);
7403 else if (cur->state == XML_SCHEMAS_ATTR_MISSING) {
7404 if (cur->decl->ref != NULL)
7405 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
7406 "Attribute %s on %s is required but missing\n",
7407 cur->decl->ref, node->name);
7408 else
7409 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
7410 "Attribute %s on %s is required but missing\n",
7411 cur->decl->name, node->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007412 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007413 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007414 cur = cur->next;
7415 }
7416
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007417 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007418}
7419
William M. Brack29aa7722004-05-12 00:27:56 +00007420#if 0 /* Not currently used - remove if ever needed */
Daniel Veillard4255d502002-04-16 15:50:10 +00007421/**
7422 * xmlSchemaValidateSimpleContent:
7423 * @ctxt: a schema validation context
7424 * @elem: an element
7425 * @type: the type declaration
7426 *
7427 * Validate the content of an element expected to be a simple type
7428 *
7429 * Returns 0 if the element is schemas valid, a positive error code
7430 * number otherwise and -1 in case of internal or API error.
7431 */
7432static int
7433xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007434 xmlNodePtr node ATTRIBUTE_UNUSED)
7435{
Daniel Veillard4255d502002-04-16 15:50:10 +00007436 xmlNodePtr child;
7437 xmlSchemaTypePtr type, base;
7438 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00007439 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007440
7441 child = ctxt->node;
7442 type = ctxt->type;
7443
7444 /*
7445 * Validation Rule: Element Locally Valid (Type): 3.1.3
7446 */
7447 value = xmlNodeGetContent(child);
7448 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
7449 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007450 case XML_SCHEMA_TYPE_RESTRICTION:{
7451 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00007452
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007453 base = type->baseType;
7454 if (base != NULL) {
7455 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
7456 } else {
7457 TODO}
7458 if (ret == 0) {
7459 facet = type->facets;
7460 ret =
7461 xmlSchemaValidateFacets(ctxt, base, facet, value);
7462 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007463 /*
7464 * This should attempt to validate the attributes even
7465 * when validation of the value failed.
7466 */
7467 /*
7468 if (type->attributes != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00007469 ret = xmlSchemaValidateAttributes(ctxt, node,
7470 type->attributes);
7471 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007472 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007473 break;
7474 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007475 case XML_SCHEMA_TYPE_EXTENSION:{
7476 TODO
7477 break;
7478 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007479 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007480 TODO
7481 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007482 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007483 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00007484
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007485 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007486}
William M. Brack29aa7722004-05-12 00:27:56 +00007487#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00007488
7489/**
7490 * xmlSchemaValidateCheckNodeList
7491 * @nodelist: the list of nodes
7492 *
7493 * Check the node list is only made of text nodes and entities pointing
7494 * to text nodes
7495 *
7496 * Returns 1 if true, 0 if false and -1 in case of error
7497 */
7498static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007499xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
7500{
Daniel Veillard4255d502002-04-16 15:50:10 +00007501 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007502 if (nodelist->type == XML_ENTITY_REF_NODE) {
7503 TODO /* implement recursion in the entity content */
7504 }
7505 if ((nodelist->type != XML_TEXT_NODE) &&
7506 (nodelist->type != XML_COMMENT_NODE) &&
7507 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +00007508 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007509 return (0);
7510 }
7511 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007512 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007513 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007514}
7515
7516/**
7517 * xmlSchemaSkipIgnored:
7518 * @ctxt: a schema validation context
7519 * @type: the current type context
7520 * @node: the top node.
7521 *
7522 * Skip ignorable nodes in that context
7523 *
7524 * Returns the new sibling
7525 * number otherwise and -1 in case of internal or API error.
7526 */
7527static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00007528xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007529 xmlSchemaTypePtr type, xmlNodePtr node)
7530{
Daniel Veillard4255d502002-04-16 15:50:10 +00007531 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007532
Daniel Veillard4255d502002-04-16 15:50:10 +00007533 /*
7534 * TODO complete and handle entities
7535 */
7536 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007537 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00007538 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007539 ((node->type == XML_COMMENT_NODE) ||
7540 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
7541 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
7542 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
7543 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007544 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007545 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007546}
7547
7548/**
7549 * xmlSchemaValidateCallback:
7550 * @ctxt: a schema validation context
7551 * @name: the name of the element detected (might be NULL)
7552 * @type: the type
7553 *
7554 * A transition has been made in the automata associated to an element
7555 * content model
7556 */
7557static void
7558xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007559 const xmlChar * name ATTRIBUTE_UNUSED,
7560 xmlSchemaTypePtr type, xmlNodePtr node)
7561{
Daniel Veillard4255d502002-04-16 15:50:10 +00007562 xmlSchemaTypePtr oldtype = ctxt->type;
7563 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007564
Daniel Veillard4255d502002-04-16 15:50:10 +00007565#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00007566 xmlGenericError(xmlGenericErrorContext,
7567 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007568 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00007569#endif
7570 ctxt->type = type;
7571 ctxt->node = node;
7572 xmlSchemaValidateContent(ctxt, node);
7573 ctxt->type = oldtype;
7574 ctxt->node = oldnode;
7575}
7576
7577
7578#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007579
Daniel Veillard4255d502002-04-16 15:50:10 +00007580/**
7581 * xmlSchemaValidateSimpleRestrictionType:
7582 * @ctxt: a schema validation context
7583 * @node: the top node.
7584 *
7585 * Validate the content of a restriction type.
7586 *
7587 * Returns 0 if the element is schemas valid, a positive error code
7588 * number otherwise and -1 in case of internal or API error.
7589 */
7590static int
7591xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
7592 xmlNodePtr node)
7593{
7594 xmlNodePtr child;
7595 xmlSchemaTypePtr type;
7596 int ret;
7597
7598 child = ctxt->node;
7599 type = ctxt->type;
7600
7601 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00007602 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7603 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
7604 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007605 return (-1);
7606 }
7607 /*
7608 * Only text and text based entities references shall be found there
7609 */
7610 ret = xmlSchemaValidateCheckNodeList(child);
7611 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007612 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7613 "Internal error: xmlSchemaValidateSimpleType %s content\n",
7614 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007615 return (-1);
7616 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007617 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
7618 "Element %s content is not a simple type\n",
7619 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007620 return (-1);
7621 }
7622 ctxt->type = type->subtypes;
7623 xmlSchemaValidateContent(ctxt, node);
7624 ctxt->type = type;
7625 return (ret);
7626}
7627#endif
7628
7629/**
7630 * xmlSchemaValidateSimpleType:
7631 * @ctxt: a schema validation context
7632 * @node: the top node.
7633 *
7634 * Validate the content of an simple type.
7635 *
7636 * Returns 0 if the element is schemas valid, a positive error code
7637 * number otherwise and -1 in case of internal or API error.
7638 */
7639static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007640xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7641{
Daniel Veillard4255d502002-04-16 15:50:10 +00007642 xmlNodePtr child;
William M. Bracke7091952004-05-11 15:09:58 +00007643 xmlSchemaTypePtr type, base, variety;
Daniel Veillard4255d502002-04-16 15:50:10 +00007644 xmlAttrPtr attr;
7645 int ret;
William M. Bracke7091952004-05-11 15:09:58 +00007646 xmlChar *value;
7647
Daniel Veillard4255d502002-04-16 15:50:10 +00007648
7649 child = ctxt->node;
7650 type = ctxt->type;
7651
7652 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00007653 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7654 "Internal error: xmlSchemaValidateSimpleType %s\n",
7655 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007656 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007657 }
7658 /*
7659 * Only text and text based entities references shall be found there
7660 */
7661 ret = xmlSchemaValidateCheckNodeList(child);
7662 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007663 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7664 "Internal error: xmlSchemaValidateSimpleType %s content\n",
7665 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007666 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007667 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007668 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
7669 "Element %s content is not a simple type\n",
7670 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007671 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007672 }
7673 /*
7674 * Validation Rule: Element Locally Valid (Type): 3.1.1
William M. Bracke7091952004-05-11 15:09:58 +00007675 */
7676
Daniel Veillard4255d502002-04-16 15:50:10 +00007677 attr = node->properties;
7678 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007679 if ((attr->ns == NULL) ||
7680 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
7681 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
7682 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
7683 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
7684 (!xmlStrEqual
7685 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
William M. Bracke7091952004-05-11 15:09:58 +00007686 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
7687 "Element %s: attribute %s should not be present\n",
7688 node->name, attr->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007689 return (ctxt->err);
7690 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007691 }
William M. Bracke7091952004-05-11 15:09:58 +00007692 /* TODO:
7693 * If {variety} is ·atomic· then the {variety} of {base type definition}
7694 * must be ·atomic·.
7695 * If {variety} is ·list· then the {variety} of {item type definition}
7696 * must be either ·atomic· or ·union·.
7697 * If {variety} is ·union· then {member type definitions} must be a list
7698 * of datatype definitions.
7699 */
7700 if (type->subtypes == NULL) {
7701 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7702 "Internal error: xmlSchemaValidateSimpleType; "
7703 "simple type %s does not define a variety\n",
7704 node->name, NULL);
7705 return (ctxt->err);
7706 }
7707 /* Varieties: Restriction or List or Union. */
7708 variety = type->subtypes;
7709 ctxt->type = variety;
7710 value = xmlNodeGetContent(child);
7711 switch (variety->type) {
7712 case XML_SCHEMA_TYPE_RESTRICTION:{
7713 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00007714
William M. Bracke7091952004-05-11 15:09:58 +00007715 base = variety->baseType;
7716 if (base != NULL) {
7717 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
7718 } else {
7719 TODO}
7720 if (ret == 0) {
7721 facet = variety->facets;
7722 ret =
7723 xmlSchemaValidateFacets(ctxt, base, facet, value);
7724 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007725 /* Removed due to changes of attribute validation:
William M. Bracke7091952004-05-11 15:09:58 +00007726 if ((ret == 0) && (variety->attributes != NULL)) {
7727 ret = xmlSchemaValidateAttributes(ctxt, node,
7728 variety->attributes);
7729 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007730 */
William M. Bracke7091952004-05-11 15:09:58 +00007731 break;
7732 }
7733 case XML_SCHEMA_TYPE_LIST:
7734 case XML_SCHEMA_TYPE_UNION: {
7735 ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
7736 break;
7737 }
7738 default:{
7739 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7740 "Internal error: xmlSchemaValidateSimpleType; "
7741 "simple type %s defines unknown content: %s\n",
7742 variety->name, NULL);
7743 ret = ctxt->err;
7744 }
7745 }
7746 if (value != NULL)
7747 xmlFree(value);
7748
7749 /* This was removed, since a simple content is not a content of a
7750 * simple type, but of a complex type.
7751 * ret = xmlSchemaValidateSimpleContent(ctxt, node);
7752 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007753 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007754 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007755}
7756
7757/**
7758 * xmlSchemaValidateElementType:
7759 * @ctxt: a schema validation context
7760 * @node: the top node.
7761 *
7762 * Validate the content of an element type.
7763 * Validation Rule: Element Locally Valid (Complex Type)
7764 *
7765 * Returns 0 if the element is schemas valid, a positive error code
7766 * number otherwise and -1 in case of internal or API error.
7767 */
7768static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007769xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7770{
Daniel Veillard4255d502002-04-16 15:50:10 +00007771 xmlNodePtr child;
7772 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007773 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00007774 xmlSchemaElementPtr decl;
Daniel Veillard3646d642004-06-02 19:19:14 +00007775 int ret;
7776 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
7777
7778 /*
7779 * TODO: Look into "xmlSchemaValidateElement" for missing parts, which should
7780 * go in here as well.
7781 */
7782
7783 /* TODO: Is this one called always with an element declaration as the
7784 * context's type?
7785 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007786
7787 oldregexp = ctxt->regexp;
7788
7789 child = ctxt->node;
7790 type = ctxt->type;
7791
7792 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00007793 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7794 "Internal error: xmlSchemaValidateElementType\n",
7795 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007796 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007797 }
7798 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007799 if (type->minOccurs > 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007800 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
7801 "Element %s: missing child %s\n",
7802 node->name, type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007803 }
7804 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00007805 }
7806
7807 /*
7808 * Verify the element matches
7809 */
7810 if (!xmlStrEqual(child->name, type->name)) {
William M. Bracke7091952004-05-11 15:09:58 +00007811 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
7812 "Element %s: missing child %s found %s\n",
7813 node->name, type->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007814 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00007815 }
7816 /*
7817 * Verify the attributes
7818 */
Daniel Veillard3646d642004-06-02 19:19:14 +00007819
7820 attrs = ctxt->attr;
7821 attrTop = ctxt->attrTop;
7822
Daniel Veillard4255d502002-04-16 15:50:10 +00007823 xmlSchemaRegisterAttributes(ctxt, child->properties);
Daniel Veillard3646d642004-06-02 19:19:14 +00007824
7825 /*
7826 * An element declaration does not hold any information about
7827 * attributes; thus, the following was removed.
7828 */
7829 /* xmlSchemaValidateAttributes(ctxt, child, type->attributes); */
7830
Daniel Veillard4255d502002-04-16 15:50:10 +00007831 /*
7832 * Verify the element content recursively
7833 */
7834 decl = (xmlSchemaElementPtr) type;
7835 oldregexp = ctxt->regexp;
7836 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007837 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
7838 (xmlRegExecCallbacks)
7839 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00007840#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007841 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00007842#endif
7843 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007844 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
7845 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00007846
7847 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007848 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007849#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007850 xmlGenericError(xmlGenericErrorContext,
7851 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007852#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007853 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007854 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
7855 "Element %s content check failed\n",
7856 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007857 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007858 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
7859 "Element %s content check failure\n",
7860 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007861#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007862 } else {
7863 xmlGenericError(xmlGenericErrorContext,
7864 "Element %s content check succeeded\n",
7865 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00007866
7867#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007868 }
7869 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00007870 }
7871 /*
7872 * Verify that all attributes were Schemas-validated
7873 */
7874 xmlSchemaCheckAttributes(ctxt, node);
Daniel Veillard3646d642004-06-02 19:19:14 +00007875 if (ctxt->attr != NULL)
7876 xmlSchemaFreeAttributeStates(ctxt->attr);
7877 ctxt->attr = attrs;
7878 ctxt->attrTop = attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +00007879 ctxt->regexp = oldregexp;
Daniel Veillard4255d502002-04-16 15:50:10 +00007880 ctxt->node = child;
7881 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007882 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00007883}
7884
7885/**
7886 * xmlSchemaValidateBasicType:
7887 * @ctxt: a schema validation context
7888 * @node: the top node.
7889 *
7890 * Validate the content of an element expected to be a basic type type
7891 *
7892 * Returns 0 if the element is schemas valid, a positive error code
7893 * number otherwise and -1 in case of internal or API error.
7894 */
7895static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007896xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7897{
Daniel Veillard4255d502002-04-16 15:50:10 +00007898 int ret;
7899 xmlNodePtr child, cur;
7900 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007901 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00007902
7903 child = ctxt->node;
7904 type = ctxt->type;
7905
7906 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00007907 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
7908 "Internal error: xmlSchemaValidateBasicType\n",
7909 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007910 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007911 }
7912 /*
7913 * First check the content model of the node.
7914 */
7915 cur = child;
7916 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007917 switch (cur->type) {
7918 case XML_TEXT_NODE:
7919 case XML_CDATA_SECTION_NODE:
7920 case XML_PI_NODE:
7921 case XML_COMMENT_NODE:
7922 case XML_XINCLUDE_START:
7923 case XML_XINCLUDE_END:
7924 break;
7925 case XML_ENTITY_REF_NODE:
7926 case XML_ENTITY_NODE:
7927 TODO break;
7928 case XML_ELEMENT_NODE:
William M. Bracke7091952004-05-11 15:09:58 +00007929 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
7930 "Element %s: child %s should not be present\n",
7931 node->name, cur->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007932 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00007933 case XML_ATTRIBUTE_NODE:
7934 case XML_DOCUMENT_NODE:
7935 case XML_DOCUMENT_TYPE_NODE:
7936 case XML_DOCUMENT_FRAG_NODE:
7937 case XML_NOTATION_NODE:
7938 case XML_HTML_DOCUMENT_NODE:
7939 case XML_DTD_NODE:
7940 case XML_ELEMENT_DECL:
7941 case XML_ATTRIBUTE_DECL:
7942 case XML_ENTITY_DECL:
7943 case XML_NAMESPACE_DECL:
7944#ifdef LIBXML_DOCB_ENABLED
7945 case XML_DOCB_DOCUMENT_NODE:
7946#endif
William M. Bracke7091952004-05-11 15:09:58 +00007947 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
7948 "Element %s: node type of node unexpected here\n",
7949 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007950 return (ctxt->err);
7951 }
7952 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007953 }
7954 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007955 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007956 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007957 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00007958
7959 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007960 xmlSchemaFreeValue(ctxt->value);
7961 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007962 }
7963 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
7964 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007965 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00007966 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +00007967 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
7968 "Element %s: failed to validate basic type %s\n",
7969 node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00007970 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007971 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00007972}
7973
7974/**
7975 * xmlSchemaValidateComplexType:
7976 * @ctxt: a schema validation context
7977 * @node: the top node.
7978 *
7979 * Validate the content of an element expected to be a complex type type
7980 * xmlschema-1.html#cvc-complex-type
7981 * Validation Rule: Element Locally Valid (Complex Type)
7982 *
7983 * Returns 0 if the element is schemas valid, a positive error code
7984 * number otherwise and -1 in case of internal or API error.
7985 */
7986static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007987xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
7988{
Daniel Veillard4255d502002-04-16 15:50:10 +00007989 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00007990 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007991 int ret;
7992
Daniel Veillard3646d642004-06-02 19:19:14 +00007993 /* TODO: Handle xsd:restriction & xsd:extension */
7994
Daniel Veillard4255d502002-04-16 15:50:10 +00007995 child = ctxt->node;
7996 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00007997 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00007998
Daniel Veillard4255d502002-04-16 15:50:10 +00007999 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008000 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008001 if (type->baseType != NULL) {
8002 } else if (child != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008003 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY,
8004 "Element %s is supposed to be empty\n",
8005 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008006 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008007 /* Removed due to changes of attribute validation:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008008 if (type->attributes != NULL) {
8009 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
8010 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008011 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008012 subtype = type->subtypes;
8013 while (subtype != NULL) {
8014 ctxt->type = subtype;
8015 xmlSchemaValidateComplexType(ctxt, node);
8016 subtype = subtype->next;
8017 }
8018 break;
8019 case XML_SCHEMA_CONTENT_ELEMENTS:
8020 case XML_SCHEMA_CONTENT_MIXED:
8021 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
8022 /*
8023 * Skip ignorable nodes in that context
8024 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008025 /* ComplexType, ComplexContent */
8026 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008027 child = xmlSchemaSkipIgnored(ctxt, type, child);
8028 while (child != NULL) {
8029 if (child->type == XML_ELEMENT_NODE) {
8030 ret = xmlRegExecPushString(ctxt->regexp,
8031 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00008032#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008033 if (ret < 0)
8034 xmlGenericError(xmlGenericErrorContext,
8035 " --> %s Error\n", child->name);
8036 else
8037 xmlGenericError(xmlGenericErrorContext,
8038 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008039#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008040 }
8041 child = child->next;
8042 /*
8043 * Skip ignorable nodes in that context
8044 */
8045 child = xmlSchemaSkipIgnored(ctxt, type, child);
8046 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008047 }
8048
William M. Bracke7091952004-05-11 15:09:58 +00008049 if (((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
8050 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS)) &&
8051 (type->subtypes != NULL)) {
8052 TODO
8053 }
8054
Daniel Veillard3646d642004-06-02 19:19:14 +00008055 /* Removed due to changes of attribute validation:
Daniel Veillardf2a12832003-11-24 13:04:35 +00008056 if (type->attributes != NULL) {
8057 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
8058 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008059 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008060 break;
8061 case XML_SCHEMA_CONTENT_BASIC:{
8062 if (type->subtypes != NULL) {
8063 ctxt->type = type->subtypes;
8064 xmlSchemaValidateComplexType(ctxt, node);
8065 }
8066 if (type->baseType != NULL) {
8067 ctxt->type = type->baseType;
William M. Bracke7091952004-05-11 15:09:58 +00008068 if (type->baseType->type == XML_SCHEMA_TYPE_BASIC)
8069 xmlSchemaValidateBasicType(ctxt, node);
8070 else if (type->baseType->type == XML_SCHEMA_TYPE_COMPLEX)
8071 xmlSchemaValidateComplexType(ctxt, node);
Daniel Veillard3646d642004-06-02 19:19:14 +00008072 /* TODO: This might be incorrect. */
William M. Bracke7091952004-05-11 15:09:58 +00008073 else if (type->baseType->type == XML_SCHEMA_TYPE_SIMPLE)
8074 xmlSchemaValidateSimpleType(ctxt, node);
8075 else
8076 xmlGenericError(xmlGenericErrorContext,
8077 "unexpected content type of base: %d\n",
8078 type->contentType);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008079 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008080 /* Removed due to changes of attribute validation:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008081 if (type->attributes != NULL) {
8082 xmlSchemaValidateAttributes(ctxt, node,
8083 type->attributes);
8084 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008085 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008086 ctxt->type = type;
8087 break;
8088 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008089 case XML_SCHEMA_CONTENT_SIMPLE:{
8090 if (type->subtypes != NULL) {
8091 ctxt->type = type->subtypes;
8092 xmlSchemaValidateComplexType(ctxt, node);
8093 }
8094 if (type->baseType != NULL) {
8095 ctxt->type = type->baseType;
8096 xmlSchemaValidateComplexType(ctxt, node);
8097 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008098 /* Removed due to changes of attribute validation:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008099 if (type->attributes != NULL) {
8100 xmlSchemaValidateAttributes(ctxt, node,
8101 type->attributes);
8102 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008103 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008104 ctxt->type = type;
8105 break;
8106 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008107 default:
8108 TODO xmlGenericError(xmlGenericErrorContext,
8109 "unimplemented content type %d\n",
8110 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00008111 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008112 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
8113 xmlSchemaValidateAttributes(ctxt, node, type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008114 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008115}
8116
8117/**
8118 * xmlSchemaValidateContent:
8119 * @ctxt: a schema validation context
8120 * @elem: an element
8121 * @type: the type declaration
8122 *
8123 * Validate the content of an element against the type.
8124 *
8125 * Returns 0 if the element is schemas valid, a positive error code
8126 * number otherwise and -1 in case of internal or API error.
8127 */
8128static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008129xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
8130{
Daniel Veillard4255d502002-04-16 15:50:10 +00008131 xmlNodePtr child;
8132 xmlSchemaTypePtr type;
8133
8134 child = ctxt->node;
8135 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00008136 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00008137
Daniel Veillard3646d642004-06-02 19:19:14 +00008138 /*
8139 * Removed, since redundant.
8140 */
8141 /* xmlSchemaValidateAttributes(ctxt, node, type->attributes); */
Daniel Veillard82bbbd42003-05-11 20:16:09 +00008142 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00008143
Daniel Veillard4255d502002-04-16 15:50:10 +00008144 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008145 case XML_SCHEMA_TYPE_ANY:
8146 /* Any type will do it, fine */
8147 TODO /* handle recursivity */
8148 break;
8149 case XML_SCHEMA_TYPE_COMPLEX:
8150 xmlSchemaValidateComplexType(ctxt, node);
8151 break;
8152 case XML_SCHEMA_TYPE_ELEMENT:{
8153 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
8154
8155 /*
8156 * Handle element reference here
8157 */
8158 if (decl->ref != NULL) {
8159 if (decl->refDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008160 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
8161 "Internal error: element reference %s "
8162 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008163 return (-1);
8164 }
8165 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
8166 decl = decl->refDecl;
8167 }
William M. Bracke7091952004-05-11 15:09:58 +00008168 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008169 xmlSchemaValidateElementType(ctxt, node);
8170 ctxt->type = type;
8171 break;
8172 }
8173 case XML_SCHEMA_TYPE_BASIC:
8174 xmlSchemaValidateBasicType(ctxt, node);
8175 break;
8176 case XML_SCHEMA_TYPE_FACET:
8177 TODO break;
8178 case XML_SCHEMA_TYPE_SIMPLE:
8179 xmlSchemaValidateSimpleType(ctxt, node);
8180 break;
8181 case XML_SCHEMA_TYPE_SEQUENCE:
8182 TODO break;
8183 case XML_SCHEMA_TYPE_CHOICE:
8184 TODO break;
8185 case XML_SCHEMA_TYPE_ALL:
8186 TODO break;
8187 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8188 TODO break;
8189 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8190 TODO break;
8191 case XML_SCHEMA_TYPE_UR:
8192 TODO break;
8193 case XML_SCHEMA_TYPE_RESTRICTION:
8194 /*xmlSchemaValidateRestrictionType(ctxt, node); */
8195 TODO break;
8196 case XML_SCHEMA_TYPE_EXTENSION:
8197 TODO break;
8198 case XML_SCHEMA_TYPE_ATTRIBUTE:
8199 TODO break;
8200 case XML_SCHEMA_TYPE_GROUP:
8201 TODO break;
8202 case XML_SCHEMA_TYPE_NOTATION:
8203 TODO break;
8204 case XML_SCHEMA_TYPE_LIST:
8205 TODO break;
8206 case XML_SCHEMA_TYPE_UNION:
8207 TODO break;
8208 case XML_SCHEMA_FACET_MININCLUSIVE:
8209 TODO break;
8210 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8211 TODO break;
8212 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8213 TODO break;
8214 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8215 TODO break;
8216 case XML_SCHEMA_FACET_TOTALDIGITS:
8217 TODO break;
8218 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8219 TODO break;
8220 case XML_SCHEMA_FACET_PATTERN:
8221 TODO break;
8222 case XML_SCHEMA_FACET_ENUMERATION:
8223 TODO break;
8224 case XML_SCHEMA_FACET_WHITESPACE:
8225 TODO break;
8226 case XML_SCHEMA_FACET_LENGTH:
8227 TODO break;
8228 case XML_SCHEMA_FACET_MAXLENGTH:
8229 TODO break;
8230 case XML_SCHEMA_FACET_MINLENGTH:
8231 TODO break;
8232 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
8233 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +00008234 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8235 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00008236 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008237 /*
8238 * Removed, since redundant.
8239 */
8240 /* xmlSchemaValidateAttributes(ctxt, node, type->attributes); */
Daniel Veillard4255d502002-04-16 15:50:10 +00008241
8242 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008243 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008244 ctxt->node = ctxt->node->next;
8245 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008246 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008247}
8248
8249/**
8250 * xmlSchemaValidateType:
8251 * @ctxt: a schema validation context
8252 * @elem: an element
8253 * @type: the list of type declarations
8254 *
8255 * Validate the content of an element against the types.
8256 *
8257 * Returns 0 if the element is schemas valid, a positive error code
8258 * number otherwise and -1 in case of internal or API error.
8259 */
8260static int
8261xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008262 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
8263{
Daniel Veillard4255d502002-04-16 15:50:10 +00008264 xmlChar *nil;
8265
Daniel Veillard2db8c122003-07-08 12:16:59 +00008266 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008267 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00008268
Daniel Veillard3646d642004-06-02 19:19:14 +00008269 /* This one is called by "xmlSchemaValidateElementType" and
8270 * "xmlSchemaValidateElement".
8271 */
8272
Daniel Veillard4255d502002-04-16 15:50:10 +00008273 /*
8274 * 3.3.4 : 2
8275 */
8276 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
William M. Bracke7091952004-05-11 15:09:58 +00008277 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
8278 "Element declaration %s is abstract\n",
8279 elemDecl->name, NULL);
8280 /* Changed, since the element declaration is abstract and not
8281 * the element itself. */
8282 /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
8283 "Element %s is abstract\n", elem->name, NULL); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008284 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008285 }
8286 /*
8287 * 3.3.4: 3
8288 */
8289 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
8290 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008291 /* 3.3.4: 3.2 */
8292 if (xmlStrEqual(nil, BAD_CAST "true")) {
8293 if (elem->children != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008294 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
8295 "Element %s is not empty\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008296 return (ctxt->err);
8297 }
8298 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
8299 (elemDecl->value != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00008300 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
8301 "Empty element %s cannot get a fixed value\n",
8302 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008303 return (ctxt->err);
8304 }
8305 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008306 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008307 /* 3.3.4: 3.1 */
8308 if (nil != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008309 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
8310 "Element %s with xs:nil but not nillable\n",
8311 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008312 xmlFree(nil);
8313 return (ctxt->err);
8314 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008315 }
8316
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008317 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00008318
8319 ctxt->type = elemDecl->subtypes;
8320 ctxt->node = elem->children;
8321 xmlSchemaValidateContent(ctxt, elem);
Daniel Veillard3646d642004-06-02 19:19:14 +00008322 /* Removed, since an element declaration does not hold any attribute
8323 * declarations */
8324 /* xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008325
8326 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008327}
8328
8329
8330/**
8331 * xmlSchemaValidateAttributes:
8332 * @ctxt: a schema validation context
8333 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +00008334 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +00008335 *
8336 * Validate the attributes of an element.
8337 *
8338 * Returns 0 if the element is schemas valid, a positive error code
8339 * number otherwise and -1 in case of internal or API error.
8340 */
8341static int
Daniel Veillard3646d642004-06-02 19:19:14 +00008342xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008343{
Daniel Veillard3646d642004-06-02 19:19:14 +00008344 int ret;
8345 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +00008346 xmlChar *value;
Daniel Veillard3646d642004-06-02 19:19:14 +00008347 xmlSchemaAttributeLinkPtr attrUse;
8348 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00008349 int found;
William M. Brack803812b2004-06-03 02:11:24 +00008350 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00008351#ifdef DEBUG_ATTR_VALIDATION
8352 int redundant = 0;
8353#endif
8354 if (type->type != XML_SCHEMA_TYPE_COMPLEX) {
8355 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INTERNAL,
8356 "Internal error: xmlSchemaValidateAttributes: "
8357 "given type \"%s\"is not a complexType\n",
8358 type->name, NULL);
8359 return(-1);
8360 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008361
Daniel Veillard3646d642004-06-02 19:19:14 +00008362 if ((type->attributeUses == NULL) && (type->attributeWildcard == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008363 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008364
8365 attrUse = type->attributeUses;
8366
8367 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00008368 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00008369 attrDecl = attrUse->attr;
8370#ifdef DEBUG_ATTR_VALIDATION
8371 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
8372 printf("attr use - use: %d\n", attrDecl->occurs);
8373#endif
8374 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
8375
8376 if (curState->decl == attrUse->attr) {
8377#ifdef DEBUG_ATTR_VALIDATION
8378 redundant = 1;
8379#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008380 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008381 attr = curState->attr;
8382#ifdef DEBUG_ATTR_VALIDATION
8383 printf("attr - name: %s\n", attr->name);
8384 if (attr->ns != NULL)
8385 printf("attr - ns: %s\n", attr->ns->href);
8386 else
8387 printf("attr - ns: none\n");
8388#endif
8389 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008390 if (attr == NULL)
8391 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +00008392 if (attrDecl->ref != NULL) {
8393 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008394 continue;
8395 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008396 if ((attrDecl->refNs == NULL) ||
8397 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008398 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +00008399 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008400 continue;
8401 }
8402 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00008403 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008404 continue;
8405 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008406 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008407 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008408 if (attr->ns == NULL) {
8409 /*
William M. Bracke7091952004-05-11 15:09:58 +00008410 * accept an unqualified attribute only if the target
8411 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008412 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008413 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +00008414 /*
8415 * This check was removed, since the target namespace
8416 * was evaluated during parsing and already took
8417 * "attributeFormDefault" into account.
8418 */
8419 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008420 continue;
8421 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00008422 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008423 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +00008424 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008425 attr->ns->href))
8426 continue;
8427 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008428 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008429#ifdef DEBUG_ATTR_VALIDATION
8430 printf("found\n");
8431#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00008432 found = 1;
William M. Brack767265d2004-06-03 10:50:29 +00008433 ctxt->cur = (xmlNodePtr) attr;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00008434
Daniel Veillard3646d642004-06-02 19:19:14 +00008435 if (attrDecl->subtypes == NULL) {
8436 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
8437 curState->decl = attrDecl;
8438 /*
8439 * This could be put into "xmlSchemaCheckAttributes" as well, but
8440 * since it reports an internal error, it better stays here to ease
8441 * debugging.
8442 */
William M. Bracke7091952004-05-11 15:09:58 +00008443 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
8444 "Internal error: attribute %s type not resolved\n",
8445 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008446 continue;
8447 }
8448 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00008449 ret = xmlSchemaValidateSimpleValue(ctxt, attrDecl->subtypes,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008450 value);
Daniel Veillard3646d642004-06-02 19:19:14 +00008451 if (ret != 0)
8452 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
8453 else
8454 curState->state = XML_SCHEMAS_ATTR_CHECKED;
8455 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008456 if (value != NULL) {
8457 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +00008458 }
8459 }
8460 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
8461 xmlSchemaAttrStatePtr tmp;
8462
8463#ifdef DEBUG_ATTR_VALIDATION
8464 printf("required attr not found\n");
8465#endif
8466 /*
8467 * Add a new dummy attribute state.
8468 */
8469 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
8470 if (tmp == NULL) {
8471 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
8472 return (-1);
8473 }
8474 tmp->attr = NULL;
8475 tmp->state = XML_SCHEMAS_ATTR_MISSING;
8476 tmp->decl = attrDecl;
8477 tmp->next = NULL;
8478
8479 if (reqAttrStates == NULL) {
8480 reqAttrStates = tmp;
8481 reqAttrStatesTop = tmp;
8482 } else {
8483 reqAttrStatesTop->next = tmp;
8484 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008485 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008486
8487 }
8488 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008489 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008490 /*
8491 * Add required attributes to the attribute states of the context.
8492 */
8493 if (reqAttrStates != NULL) {
8494 if (ctxt->attr == NULL) {
8495 ctxt->attr = reqAttrStates;
8496 } else {
8497 ctxt->attrTop->next = reqAttrStates;
8498 }
8499 ctxt->attrTop = reqAttrStatesTop;
8500 }
8501 /*
8502 * Process wildcards.
8503 */
8504 if (type->attributeWildcard != NULL) {
8505#ifdef DEBUG_ATTR_VALIDATION
8506 xmlSchemaWildcardNsPtr ns;
8507 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
8508 if (type->attributeWildcard->any)
8509 printf("type: any\n");
8510 else if (type->attributeWildcard->negNsSet != NULL) {
8511 printf("type: negated\n");
8512 if (type->attributeWildcard->negNsSet->value == NULL)
8513 printf("ns: (absent)\n");
8514 else
8515 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
8516 } else if (type->attributeWildcard->nsSet != NULL) {
8517 printf("type: set\n");
8518 ns = type->attributeWildcard->nsSet;
8519 while (ns != NULL) {
8520 if (ns->value == NULL)
8521 printf("ns: (absent)\n");
8522 else
8523 printf("ns: %s\n", ns->value);
8524 ns = ns->next;
8525 }
8526 } else
8527 printf("empty\n");
8528
8529#endif
8530 /*
8531 * TODO: Implement processContents.
8532 */
8533 curState = ctxt->attr;
8534 while (curState != NULL) {
8535 if ((curState->state == XML_SCHEMAS_ATTR_UNKNOWN) &&
8536 (curState->attr != NULL)) {
8537 if (curState->attr->ns != NULL) {
8538 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
8539 curState->attr->ns->href))
8540 curState->state = XML_SCHEMAS_ATTR_CHECKED;
8541 } else if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
8542 NULL))
8543 curState->state = XML_SCHEMAS_ATTR_CHECKED;
8544 }
8545 curState = curState->next;
8546 }
8547 }
8548
8549#ifdef DEBUG_ATTR_VALIDATION
8550 if (redundant)
8551 xmlGenericError(xmlGenericErrorContext,
8552 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
8553 type->name);
8554#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008555 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008556}
8557
8558/**
8559 * xmlSchemaValidateElement:
8560 * @ctxt: a schema validation context
8561 * @elem: an element
8562 *
8563 * Validate an element in a tree
8564 *
8565 * Returns 0 if the element is schemas valid, a positive error code
8566 * number otherwise and -1 in case of internal or API error.
8567 */
8568static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008569xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
8570{
Daniel Veillard4255d502002-04-16 15:50:10 +00008571 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +00008572 int ret;
8573 xmlSchemaAttrStatePtr attrs, attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +00008574
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008575 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008576 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8577 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008578 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008579 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8580 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008581 }
8582 /*
8583 * special case whe elementFormDefault is unqualified for top-level elem.
8584 */
William M. Bracke7091952004-05-11 15:09:58 +00008585 /*
8586 * This was removed, since elementFormDefault does not apply to top-level
8587 * element declarations.
8588 */
8589 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008590 if ((elemDecl == NULL) && (elem->ns != NULL) &&
8591 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
8592 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
8593 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
8594 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8595 elem->name, NULL, NULL);
8596 }
William M. Bracke7091952004-05-11 15:09:58 +00008597 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008598
Daniel Veillard4255d502002-04-16 15:50:10 +00008599 /*
8600 * 3.3.4 : 1
8601 */
8602 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008603 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
8604 "Element %s not declared\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008605 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008606 }
8607 if (elemDecl->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008608 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
8609 "Element %s has no type\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008610 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008611 }
8612 /*
8613 * Verify the attributes
8614 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008615 attrs = ctxt->attr;
8616 attrTop = ctxt->attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +00008617 xmlSchemaRegisterAttributes(ctxt, elem->properties);
Daniel Veillard4255d502002-04-16 15:50:10 +00008618 /*
8619 * Verify the element content recursively
8620 */
8621 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008622 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
8623 (xmlRegExecCallbacks)
8624 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008625#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008626 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008627#endif
8628 }
8629 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008630 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008631 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008632#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008633 xmlGenericError(xmlGenericErrorContext,
8634 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008635#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008636 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00008637 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
8638 "Element %s content check failed\n",
8639 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008640 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00008641 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
8642 "Element %s content check failed\n",
8643 elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008644#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008645 } else {
8646 xmlGenericError(xmlGenericErrorContext,
8647 "Element %s content check succeeded\n",
8648 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008649
8650#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008651 }
8652 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00008653 }
8654 /*
8655 * Verify that all attributes were Schemas-validated
8656 */
8657 xmlSchemaCheckAttributes(ctxt, elem);
Daniel Veillard3646d642004-06-02 19:19:14 +00008658 if (ctxt->attr != NULL)
8659 xmlSchemaFreeAttributeStates(ctxt->attr);
8660 ctxt->attr = attrs;
8661 ctxt->attrTop = attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008662
8663 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008664}
8665
8666/**
8667 * xmlSchemaValidateDocument:
8668 * @ctxt: a schema validation context
8669 * @doc: a parsed document tree
8670 *
8671 * Validate a document tree in memory.
8672 *
8673 * Returns 0 if the document is schemas valid, a positive error code
8674 * number otherwise and -1 in case of internal or API error.
8675 */
8676static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008677xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
8678{
Daniel Veillard4255d502002-04-16 15:50:10 +00008679 xmlNodePtr root;
8680 xmlSchemaElementPtr elemDecl;
8681
8682 root = xmlDocGetRootElement(doc);
8683 if (root == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008684 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
8685 "document has no root\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008686 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008687 }
William M. Bracke7091952004-05-11 15:09:58 +00008688
Daniel Veillard4255d502002-04-16 15:50:10 +00008689 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008690 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8691 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008692 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008693 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8694 root->name, NULL, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00008695
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008696 /*
8697 * special case whe elementFormDefault is unqualified for top-level elem.
8698 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008699 /* Removed, since elementFormDefault does not apply to top level
8700 * elements */
8701 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008702 if ((elemDecl == NULL) && (root->ns != NULL) &&
8703 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
8704 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
8705 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
8706 root->name, NULL, NULL);
8707 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008708 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008709
Daniel Veillard4255d502002-04-16 15:50:10 +00008710 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00008711 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
8712 "Element %s not declared\n", root->name, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00008713 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00008714 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
Daniel Veillard3646d642004-06-02 19:19:14 +00008715 "Root element %s not global\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008716 }
8717 /*
8718 * Okay, start the recursive validation
8719 */
8720 xmlSchemaValidateElement(ctxt, root);
8721
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008722 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00008723}
8724
8725/************************************************************************
8726 * *
8727 * SAX Validation code *
8728 * *
8729 ************************************************************************/
8730
8731/************************************************************************
8732 * *
8733 * Validation interfaces *
8734 * *
8735 ************************************************************************/
8736
8737/**
8738 * xmlSchemaNewValidCtxt:
8739 * @schema: a precompiled XML Schemas
8740 *
8741 * Create an XML Schemas validation context based on the given schema
8742 *
8743 * Returns the validation context or NULL in case of error
8744 */
8745xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008746xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
8747{
Daniel Veillard4255d502002-04-16 15:50:10 +00008748 xmlSchemaValidCtxtPtr ret;
8749
8750 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
8751 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008752 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008753 return (NULL);
8754 }
8755 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
8756 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +00008757 /*
8758 * Removed due to changes of the attribute state list.
William M. Brack803812b2004-06-03 02:11:24 +00008759 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008760 /* ret->attrNr = 0; */
8761 /* ret->attrMax = 10; */
8762 /* ret->attrBase = NULL; */
8763 ret->attrTop = NULL;
8764 ret->attr = NULL;
8765 /*
8766 * Removed due to changes of the attribute state list.
William M. Brack803812b2004-06-03 02:11:24 +00008767 *
Daniel Veillard4255d502002-04-16 15:50:10 +00008768 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008769 sizeof
8770 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00008771 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008772 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
8773 free(ret);
8774 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008775 }
8776 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
Daniel Veillard3646d642004-06-02 19:19:14 +00008777 */
8778
Daniel Veillard4255d502002-04-16 15:50:10 +00008779 return (ret);
8780}
8781
8782/**
8783 * xmlSchemaFreeValidCtxt:
8784 * @ctxt: the schema validation context
8785 *
8786 * Free the resources associated to the schema validation context
8787 */
8788void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008789xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
8790{
Daniel Veillard4255d502002-04-16 15:50:10 +00008791 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008792 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008793 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00008794 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00008795 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008796 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00008797 xmlFree(ctxt);
8798}
8799
8800/**
8801 * xmlSchemaSetValidErrors:
8802 * @ctxt: a schema validation context
8803 * @err: the error function
8804 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00008805 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00008806 *
8807 * Set the error and warning callback informations
8808 */
8809void
8810xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008811 xmlSchemaValidityErrorFunc err,
8812 xmlSchemaValidityWarningFunc warn, void *ctx)
8813{
Daniel Veillard4255d502002-04-16 15:50:10 +00008814 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008815 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008816 ctxt->error = err;
8817 ctxt->warning = warn;
8818 ctxt->userData = ctx;
8819}
8820
8821/**
8822 * xmlSchemaValidateDoc:
8823 * @ctxt: a schema validation context
8824 * @doc: a parsed document tree
8825 *
8826 * Validate a document tree in memory.
8827 *
8828 * Returns 0 if the document is schemas valid, a positive error code
8829 * number otherwise and -1 in case of internal or API error.
8830 */
8831int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008832xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
8833{
Daniel Veillard4255d502002-04-16 15:50:10 +00008834 int ret;
8835
8836 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008837 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008838
8839 ctxt->doc = doc;
8840 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008841 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00008842}
8843
8844/**
8845 * xmlSchemaValidateStream:
8846 * @ctxt: a schema validation context
8847 * @input: the input to use for reading the data
8848 * @enc: an optional encoding information
8849 * @sax: a SAX handler for the resulting events
8850 * @user_data: the context to provide to the SAX handler.
8851 *
8852 * Validate a document tree in memory.
8853 *
8854 * Returns 0 if the document is schemas valid, a positive error code
8855 * number otherwise and -1 in case of internal or API error.
8856 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008857int
Daniel Veillard4255d502002-04-16 15:50:10 +00008858xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008859 xmlParserInputBufferPtr input, xmlCharEncoding enc,
8860 xmlSAXHandlerPtr sax, void *user_data)
8861{
Daniel Veillard4255d502002-04-16 15:50:10 +00008862 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008863 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008864 ctxt->input = input;
8865 ctxt->enc = enc;
8866 ctxt->sax = sax;
8867 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008868 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008869}
8870
8871#endif /* LIBXML_SCHEMAS_ENABLED */