blob: 7f1b51963a6ad72443a4b86861956fa023bc3dc3 [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.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015 * - if we don't intend to use the schema for schemas, we
16 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000018 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019#define IN_LIBXML
20#include "libxml.h"
21
22#ifdef LIBXML_SCHEMAS_ENABLED
23
24#include <string.h>
25#include <libxml/xmlmemory.h>
26#include <libxml/parser.h>
27#include <libxml/parserInternals.h>
28#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000029#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000030
31#include <libxml/xmlschemas.h>
32#include <libxml/schemasInternals.h>
33#include <libxml/xmlschemastypes.h>
34#include <libxml/xmlautomata.h>
35#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000036#include <libxml/dict.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000037
Daniel Veillarda84c0b32003-06-02 16:58:46 +000038/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000039
Daniel Veillard82bbbd42003-05-11 20:16:09 +000040/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000041
Daniel Veillard82bbbd42003-05-11 20:16:09 +000042/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000043
Daniel Veillard118aed72002-09-24 14:13:13 +000044/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000045
Daniel Veillard4255d502002-04-16 15:50:10 +000046/* #define DEBUG_AUTOMATA 1 */
47
Daniel Veillard3646d642004-06-02 19:19:14 +000048/* #define DEBUG_ATTR_VALIDATION 1 */
49
Daniel Veillard4255d502002-04-16 15:50:10 +000050#define UNBOUNDED (1 << 30)
51#define TODO \
52 xmlGenericError(xmlGenericErrorContext, \
53 "Unimplemented block at %s:%d\n", \
54 __FILE__, __LINE__);
55
Daniel Veillard5a872412002-05-22 06:40:27 +000056#define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
57
Daniel Veillard4255d502002-04-16 15:50:10 +000058/*
59 * The XML Schemas namespaces
60 */
61static const xmlChar *xmlSchemaNs = (const xmlChar *)
62 "http://www.w3.org/2001/XMLSchema";
63
64static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
65 "http://www.w3.org/2001/XMLSchema-instance";
66
67#define IS_SCHEMA(node, type) \
68 ((node != NULL) && (node->ns != NULL) && \
69 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
70 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
71
72#define XML_SCHEMAS_PARSE_ERROR 1
73
Daniel Veillardbd2904b2003-11-25 15:38:59 +000074#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
75
Daniel Veillard4255d502002-04-16 15:50:10 +000076struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000077 void *userData; /* user specific data block */
78 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
79 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +000080 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000081 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +000082 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +000083
Daniel Veillardbe9c6322003-11-22 20:37:51 +000084 xmlSchemaPtr topschema; /* The main schema */
85 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
86
Daniel Veillardd0c9c322003-10-10 00:49:42 +000087 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000088 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +000089 int counter;
90
Daniel Veillardbe9c6322003-11-22 20:37:51 +000091 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000092 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000093 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +000094
Daniel Veillardd0c9c322003-10-10 00:49:42 +000095 const char *buffer;
96 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +000097
Daniel Veillard4255d502002-04-16 15:50:10 +000098 /*
99 * Used to build complex element content models
100 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000101 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000102 xmlAutomataStatePtr start;
103 xmlAutomataStatePtr end;
104 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000105
106 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000107 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000108 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
109 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Daniel Veillard4255d502002-04-16 15:50:10 +0000110};
111
112
113#define XML_SCHEMAS_ATTR_UNKNOWN 1
114#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000115#define XML_SCHEMAS_ATTR_PROHIBITED 3
116#define XML_SCHEMAS_ATTR_MISSING 4
117#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
118#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Daniel Veillard4255d502002-04-16 15:50:10 +0000119
120typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
121typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
122struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000123 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000124 xmlAttrPtr attr;
125 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000126 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +0000127};
128
129/**
130 * xmlSchemaValidCtxt:
131 *
132 * A Schemas validation context
133 */
134
135struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000136 void *userData; /* user specific data block */
137 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
138 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000139 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000140
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000141 xmlSchemaPtr schema; /* The schema in use */
142 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000143 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000144 xmlCharEncoding enc;
145 xmlSAXHandlerPtr sax;
146 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000147
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000148 xmlDocPtr myDoc;
149 int err;
150 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000151
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000152 xmlNodePtr node;
153 xmlNodePtr cur;
154 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000155
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000156 xmlRegExecCtxtPtr regexp;
157 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000158
Daniel Veillard3646d642004-06-02 19:19:14 +0000159 xmlSchemaAttrStatePtr attrTop;
160 /* xmlSchemaAttrStatePtr attrBase; */
161 /* int attrMax; */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000162 xmlSchemaAttrStatePtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +0000163};
164
Daniel Veillard1d913862003-11-21 00:28:39 +0000165/*
166 * These are the entries in the schemas importSchemas hash table
167 */
168typedef struct _xmlSchemaImport xmlSchemaImport;
169typedef xmlSchemaImport *xmlSchemaImportPtr;
170struct _xmlSchemaImport {
171 const xmlChar *schemaLocation;
172 xmlSchemaPtr schema;
173};
Daniel Veillard4255d502002-04-16 15:50:10 +0000174
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000175/*
176 * These are the entries associated to includes in a schemas
177 */
178typedef struct _xmlSchemaInclude xmlSchemaInclude;
179typedef xmlSchemaInclude *xmlSchemaIncludePtr;
180struct _xmlSchemaInclude {
181 xmlSchemaIncludePtr next;
182
183 const xmlChar *schemaLocation;
184 xmlDocPtr doc;
185};
186
Daniel Veillard4255d502002-04-16 15:50:10 +0000187/************************************************************************
188 * *
189 * Some predeclarations *
190 * *
191 ************************************************************************/
Daniel Veillard01fa6152004-06-29 17:04:39 +0000192#if 0 /* Not currently used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000193static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
194 xmlSchemaTypePtr type,
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000195 const xmlChar * value);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000196#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000197
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000198static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
199 xmlSchemaPtr schema,
200 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000201#if 0
William M. Brack87640d52004-04-17 14:58:15 +0000202static int
203xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
204 xmlSchemaTypePtr type,
205 const xmlChar * value,
206 int fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000207#endif /* Not currently used. */
208static void
209xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
210 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
211static const char *
212xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
213static int
214xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
215 const xmlChar *value,
216 int fireErrors,
217 int applyFacets);
William M. Brack87640d52004-04-17 14:58:15 +0000218
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000219/************************************************************************
220 * *
221 * Datatype error handlers *
222 * *
223 ************************************************************************/
224
225/**
226 * xmlSchemaPErrMemory:
227 * @node: a context node
228 * @extra: extra informations
229 *
230 * Handle an out of memory condition
231 */
232static void
233xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
234 const char *extra, xmlNodePtr node)
235{
236 if (ctxt != NULL)
237 ctxt->nberrors++;
238 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
239 extra);
240}
241
242/**
243 * xmlSchemaPErr:
244 * @ctxt: the parsing context
245 * @node: the context node
246 * @error: the error code
247 * @msg: the error message
248 * @str1: extra data
249 * @str2: extra data
250 *
251 * Handle a parser error
252 */
253static void
254xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
255 const char *msg, const xmlChar * str1, const xmlChar * str2)
256{
257 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000258 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000259 void *data = NULL;
260
261 if (ctxt != NULL) {
262 ctxt->nberrors++;
263 channel = ctxt->error;
264 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000265 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000266 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000267 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000268 error, XML_ERR_ERROR, NULL, 0,
269 (const char *) str1, (const char *) str2, NULL, 0, 0,
270 msg, str1, str2);
271}
272
273/**
274 * xmlSchemaPErr2:
275 * @ctxt: the parsing context
276 * @node: the context node
277 * @node: the current child
278 * @error: the error code
279 * @msg: the error message
280 * @str1: extra data
281 * @str2: extra data
282 *
283 * Handle a parser error
284 */
285static void
286xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
287 xmlNodePtr child, int error,
288 const char *msg, const xmlChar * str1, const xmlChar * str2)
289{
290 if (child != NULL)
291 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
292 else
293 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
294}
295
Daniel Veillard01fa6152004-06-29 17:04:39 +0000296
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000297/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000298 * xmlSchemaPErrExt:
299 * @ctxt: the parsing context
300 * @node: the context node
301 * @error: the error code
302 * @strData1: extra data
303 * @strData2: extra data
304 * @strData3: extra data
305 * @msg: the message
306 * @str1: extra parameter for the message display
307 * @str2: extra parameter for the message display
308 * @str3: extra parameter for the message display
309 * @str4: extra parameter for the message display
310 * @str5: extra parameter for the message display
311 *
312 * Handle a parser error
313 */
314static void
315xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
316 const xmlChar * strData1, const xmlChar * strData2,
317 const xmlChar * strData3, const char *msg, const xmlChar * str1,
318 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
319 const xmlChar * str5)
320{
321
322 xmlGenericErrorFunc channel = NULL;
323 xmlStructuredErrorFunc schannel = NULL;
324 void *data = NULL;
325
326 if (ctxt != NULL) {
327 ctxt->nberrors++;
328 channel = ctxt->error;
329 data = ctxt->userData;
330 schannel = ctxt->serror;
331 }
332 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
333 error, XML_ERR_ERROR, NULL, 0,
334 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000335 (const char *) strData3, 0, 0, msg, str1, str2,
336 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000337}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000338
Daniel Veillard3646d642004-06-02 19:19:14 +0000339
340/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000341 * xmlSchemaVTypeErrMemory:
342 * @node: a context node
343 * @extra: extra informations
344 *
345 * Handle an out of memory condition
346 */
347static void
348xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
349 const char *extra, xmlNodePtr node)
350{
351 if (ctxt != NULL) {
352 ctxt->nberrors++;
353 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
354 }
355 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
356 extra);
357}
358
359/**
360 * xmlSchemaVErr3:
361 * @ctxt: the validation context
362 * @node: the context node
363 * @error: the error code
364 * @msg: the error message
365 * @str1: extra data
366 * @str2: extra data
367 * @str3: extra data
368 *
369 * Handle a validation error
370 */
371static void
372xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
373 const char *msg, const xmlChar *str1, const xmlChar *str2,
374 const xmlChar *str3)
375{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000376 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000377 xmlGenericErrorFunc channel = NULL;
378 void *data = NULL;
379
380 if (ctxt != NULL) {
381 ctxt->nberrors++;
382 ctxt->err = error;
383 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000384 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000385 data = ctxt->userData;
386 }
387 /* reajust to global error numbers */
388 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000389 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000390 error, XML_ERR_ERROR, NULL, 0,
391 (const char *) str1, (const char *) str2,
392 (const char *) str3, 0, 0,
393 msg, str1, str2, str3);
394}
395/**
396 * xmlSchemaVErr:
397 * @ctxt: the validation context
398 * @node: the context node
399 * @error: the error code
400 * @msg: the error message
401 * @str1: extra data
402 * @str2: extra data
403 *
404 * Handle a validation error
405 */
406static void
407xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
408 const char *msg, const xmlChar * str1, const xmlChar * str2)
409{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000410 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000411 xmlGenericErrorFunc channel = NULL;
412 void *data = NULL;
413
414 if (ctxt != NULL) {
415 ctxt->nberrors++;
416 ctxt->err = error;
417 channel = ctxt->error;
418 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000419 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000420 }
421 /* reajust to global error numbers */
422 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000423 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000424 error, XML_ERR_ERROR, NULL, 0,
425 (const char *) str1, (const char *) str2, NULL, 0, 0,
426 msg, str1, str2);
427}
Daniel Veillard4255d502002-04-16 15:50:10 +0000428
429/************************************************************************
430 * *
431 * Allocation functions *
432 * *
433 ************************************************************************/
434
435/**
436 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +0000437 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000438 *
439 * Allocate a new Schema structure.
440 *
441 * Returns the newly allocated structure or NULL in case or error
442 */
443static xmlSchemaPtr
444xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
445{
446 xmlSchemaPtr ret;
447
448 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
449 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000450 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000451 return (NULL);
452 }
453 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000454 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000455 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000456
457 return (ret);
458}
459
460/**
461 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000462 *
463 * Allocate a new Facet structure.
464 *
465 * Returns the newly allocated structure or NULL in case or error
466 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000467xmlSchemaFacetPtr
468xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000469{
470 xmlSchemaFacetPtr ret;
471
472 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
473 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000474 return (NULL);
475 }
476 memset(ret, 0, sizeof(xmlSchemaFacet));
477
478 return (ret);
479}
480
481/**
482 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +0000483 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000484 * @node: a node
485 *
486 * Allocate a new annotation structure.
487 *
488 * Returns the newly allocated structure or NULL in case or error
489 */
490static xmlSchemaAnnotPtr
491xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
492{
493 xmlSchemaAnnotPtr ret;
494
495 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
496 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000497 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000498 return (NULL);
499 }
500 memset(ret, 0, sizeof(xmlSchemaAnnot));
501 ret->content = node;
502 return (ret);
503}
504
505/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000506 * xmlSchemaFreeAnnot:
507 * @annot: a schema type structure
508 *
509 * Deallocate a annotation structure
510 */
511static void
512xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
513{
514 if (annot == NULL)
515 return;
516 xmlFree(annot);
517}
518
519/**
Daniel Veillard1d913862003-11-21 00:28:39 +0000520 * xmlSchemaFreeImport:
521 * @import: a schema import structure
522 *
523 * Deallocate an import structure
524 */
525static void
526xmlSchemaFreeImport(xmlSchemaImportPtr import)
527{
528 if (import == NULL)
529 return;
530
531 xmlSchemaFree(import->schema);
Daniel Veillard1d913862003-11-21 00:28:39 +0000532 xmlFree(import);
533}
534
535/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000536 * xmlSchemaFreeInclude:
537 * @include: a schema include structure
538 *
539 * Deallocate an include structure
540 */
541static void
542xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
543{
544 if (include == NULL)
545 return;
546
547 xmlFreeDoc(include->doc);
548 xmlFree(include);
549}
550
551/**
552 * xmlSchemaFreeIncludeList:
553 * @includes: a schema include list
554 *
555 * Deallocate an include structure
556 */
557static void
558xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
559{
560 xmlSchemaIncludePtr next;
561
562 while (includes != NULL) {
563 next = includes->next;
564 xmlSchemaFreeInclude(includes);
565 includes = next;
566 }
567}
568
569/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000570 * xmlSchemaFreeNotation:
571 * @schema: a schema notation structure
572 *
573 * Deallocate a Schema Notation structure.
574 */
575static void
576xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
577{
578 if (nota == NULL)
579 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000580 xmlFree(nota);
581}
582
583/**
584 * xmlSchemaFreeAttribute:
585 * @schema: a schema attribute structure
586 *
587 * Deallocate a Schema Attribute structure.
588 */
589static void
590xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
591{
592 if (attr == NULL)
593 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000594 xmlFree(attr);
595}
596
597/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000598 * xmlSchemaFreeWildcardNsSet:
599 * set: a schema wildcard namespace
600 *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000601 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +0000602 */
603static void
604xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
605{
606 xmlSchemaWildcardNsPtr next;
607
608 while (set != NULL) {
609 next = set->next;
610 xmlFree(set);
611 set = next;
612 }
613}
614
615/**
616 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +0000617 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +0000618 *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000619 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +0000620 */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000621void
Daniel Veillard3646d642004-06-02 19:19:14 +0000622xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
623{
624 if (wildcard == NULL)
625 return;
626 if (wildcard->annot != NULL)
627 xmlSchemaFreeAnnot(wildcard->annot);
628 if (wildcard->nsSet != NULL)
629 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
630 if (wildcard->negNsSet != NULL)
631 xmlFree(wildcard->negNsSet);
632 xmlFree(wildcard);
633}
634
635/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000636 * xmlSchemaFreeAttributeGroup:
637 * @schema: a schema attribute group structure
638 *
639 * Deallocate a Schema Attribute Group structure.
640 */
641static void
642xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
643{
644 if (attr == NULL)
645 return;
Daniel Veillard3646d642004-06-02 19:19:14 +0000646 if (attr->annot != NULL)
647 xmlSchemaFreeAnnot(attr->annot);
648 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
649 (attr->attributeWildcard != NULL))
650 xmlSchemaFreeWildcard(attr->attributeWildcard);
651
Daniel Veillard4255d502002-04-16 15:50:10 +0000652 xmlFree(attr);
653}
654
655/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000656 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +0000657 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +0000658 *
659 * Deallocate a list of schema attribute uses.
660 */
661static void
662xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
663{
664 xmlSchemaAttributeLinkPtr next;
665
666 while (attrUse != NULL) {
667 next = attrUse->next;
668 xmlFree(attrUse);
669 attrUse = next;
670 }
671}
672
673/**
Daniel Veillard01fa6152004-06-29 17:04:39 +0000674 * xmlSchemaFreeTypeLinkList:
675 * @alink: a type link
676 *
677 * Deallocate a list of types.
678 */
679static void
680xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
681{
682 xmlSchemaTypeLinkPtr next;
683
684 while (link != NULL) {
685 next = link->next;
686 xmlFree(link);
687 link = next;
688 }
689}
690
691/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000692 * xmlSchemaFreeElement:
693 * @schema: a schema element structure
694 *
695 * Deallocate a Schema Element structure.
696 */
697static void
698xmlSchemaFreeElement(xmlSchemaElementPtr elem)
699{
700 if (elem == NULL)
701 return;
Daniel Veillard32370232002-10-16 14:08:14 +0000702 if (elem->annot != NULL)
703 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000704 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000705 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000706 xmlFree(elem);
707}
708
709/**
710 * xmlSchemaFreeFacet:
711 * @facet: a schema facet structure
712 *
713 * Deallocate a Schema Facet structure.
714 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000715void
Daniel Veillard4255d502002-04-16 15:50:10 +0000716xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
717{
718 if (facet == NULL)
719 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000720 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000721 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000722 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000723 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000724 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000725 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000726 xmlFree(facet);
727}
728
729/**
730 * xmlSchemaFreeType:
731 * @type: a schema type structure
732 *
733 * Deallocate a Schema Type structure.
734 */
735void
736xmlSchemaFreeType(xmlSchemaTypePtr type)
737{
738 if (type == NULL)
739 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000740 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000741 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000742 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000743 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000744
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000745 facet = type->facets;
746 while (facet != NULL) {
747 next = facet->next;
748 xmlSchemaFreeFacet(facet);
749 facet = next;
750 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000751 }
Daniel Veillard3646d642004-06-02 19:19:14 +0000752 if (type->type != XML_SCHEMA_TYPE_BASIC) {
753 if (type->attributeUses != NULL)
754 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000755 /* TODO: There must be a way more simple than this. */
Daniel Veillard3646d642004-06-02 19:19:14 +0000756 if ((type->attributeWildcard != NULL) &&
757 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
758 ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
759 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)))) {
760 xmlSchemaFreeWildcard(type->attributeWildcard);
761 }
762 }
Daniel Veillard01fa6152004-06-29 17:04:39 +0000763 if (type->memberTypes != NULL)
764 xmlSchemaFreeTypeLinkList(type->memberTypes);
765 if (type->facetSet != NULL) {
766 xmlSchemaFacetLinkPtr next, link;
767
768 link = type->facetSet;
769 do {
770 next = link->next;
771 xmlFree(link);
772 link = next;
773 } while (link != NULL);
774 }
775
776 if ((type->subtypes != NULL) && (type->type != XML_SCHEMA_TYPE_SEQUENCE)) {
777 switch (type->subtypes->type) {
778 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
779 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
780 case XML_SCHEMA_TYPE_RESTRICTION:
781 case XML_SCHEMA_TYPE_EXTENSION:
782 case XML_SCHEMA_TYPE_UNION:
783 xmlSchemaFreeType(type->subtypes);
784 }
785 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000786 xmlFree(type);
787}
788
789/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000790 * xmlSchemaFreeTypeList:
791 * @type: a schema type structure
792 *
793 * Deallocate a Schema Type structure.
794 */
795static void
796xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
797{
798 xmlSchemaTypePtr next;
799
800 while (type != NULL) {
801 next = type->redef;
802 xmlSchemaFreeType(type);
803 type = next;
804 }
805}
806
807/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000808 * xmlSchemaFree:
809 * @schema: a schema structure
810 *
811 * Deallocate a Schema structure.
812 */
813void
814xmlSchemaFree(xmlSchemaPtr schema)
815{
816 if (schema == NULL)
817 return;
818
Daniel Veillard4255d502002-04-16 15:50:10 +0000819 if (schema->notaDecl != NULL)
820 xmlHashFree(schema->notaDecl,
821 (xmlHashDeallocator) xmlSchemaFreeNotation);
822 if (schema->attrDecl != NULL)
823 xmlHashFree(schema->attrDecl,
824 (xmlHashDeallocator) xmlSchemaFreeAttribute);
825 if (schema->attrgrpDecl != NULL)
826 xmlHashFree(schema->attrgrpDecl,
827 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
828 if (schema->elemDecl != NULL)
829 xmlHashFree(schema->elemDecl,
830 (xmlHashDeallocator) xmlSchemaFreeElement);
831 if (schema->typeDecl != NULL)
832 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000833 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000834 if (schema->groupDecl != NULL)
835 xmlHashFree(schema->groupDecl,
836 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +0000837 if (schema->schemasImports != NULL)
838 xmlHashFree(schema->schemasImports,
839 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000840 if (schema->includes != NULL) {
841 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
842 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000843 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000844 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +0000845 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000846 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000847 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000848
849 xmlFree(schema);
850}
851
852/************************************************************************
853 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000854 * Debug functions *
855 * *
856 ************************************************************************/
857
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000858#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000859
Daniel Veillard4255d502002-04-16 15:50:10 +0000860/**
861 * xmlSchemaElementDump:
862 * @elem: an element
863 * @output: the file output
864 *
865 * Dump the element
866 */
867static void
868xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000869 const xmlChar * name ATTRIBUTE_UNUSED,
870 const xmlChar * context ATTRIBUTE_UNUSED,
871 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000872{
873 if (elem == NULL)
874 return;
875
876 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +0000877 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
878 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000879 fprintf(output, ": %s ", elem->name);
880 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000881 fprintf(output, "namespace '%s' ", namespace);
882
Daniel Veillard4255d502002-04-16 15:50:10 +0000883 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000884 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000885 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000886 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000887 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000888 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000889 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000890 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000891 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000892 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000893 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000894 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000895 fprintf(output, "\n");
896 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000897 fprintf(output, " ");
898 if (elem->minOccurs != 1)
899 fprintf(output, "min: %d ", elem->minOccurs);
900 if (elem->maxOccurs >= UNBOUNDED)
901 fprintf(output, "max: unbounded\n");
902 else if (elem->maxOccurs != 1)
903 fprintf(output, "max: %d\n", elem->maxOccurs);
904 else
905 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000906 }
907 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000908 fprintf(output, " type: %s", elem->namedType);
909 if (elem->namedTypeNs != NULL)
910 fprintf(output, " ns %s\n", elem->namedTypeNs);
911 else
912 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000913 }
914 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000915 fprintf(output, " substitutionGroup: %s", elem->substGroup);
916 if (elem->substGroupNs != NULL)
917 fprintf(output, " ns %s\n", elem->substGroupNs);
918 else
919 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000920 }
921 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000922 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000923}
924
925/**
926 * xmlSchemaAnnotDump:
927 * @output: the file output
928 * @annot: a annotation
929 *
930 * Dump the annotation
931 */
932static void
933xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
934{
935 xmlChar *content;
936
937 if (annot == NULL)
938 return;
939
940 content = xmlNodeGetContent(annot->content);
941 if (content != NULL) {
942 fprintf(output, " Annot: %s\n", content);
943 xmlFree(content);
944 } else
945 fprintf(output, " Annot: empty\n");
946}
947
948/**
949 * xmlSchemaTypeDump:
950 * @output: the file output
951 * @type: a type structure
952 *
953 * Dump a SchemaType structure
954 */
955static void
956xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
957{
958 if (type == NULL) {
959 fprintf(output, "Type: NULL\n");
960 return;
961 }
962 fprintf(output, "Type: ");
963 if (type->name != NULL)
964 fprintf(output, "%s, ", type->name);
965 else
966 fprintf(output, "no name");
967 switch (type->type) {
968 case XML_SCHEMA_TYPE_BASIC:
969 fprintf(output, "basic ");
970 break;
971 case XML_SCHEMA_TYPE_SIMPLE:
972 fprintf(output, "simple ");
973 break;
974 case XML_SCHEMA_TYPE_COMPLEX:
975 fprintf(output, "complex ");
976 break;
977 case XML_SCHEMA_TYPE_SEQUENCE:
978 fprintf(output, "sequence ");
979 break;
980 case XML_SCHEMA_TYPE_CHOICE:
981 fprintf(output, "choice ");
982 break;
983 case XML_SCHEMA_TYPE_ALL:
984 fprintf(output, "all ");
985 break;
986 case XML_SCHEMA_TYPE_UR:
987 fprintf(output, "ur ");
988 break;
989 case XML_SCHEMA_TYPE_RESTRICTION:
990 fprintf(output, "restriction ");
991 break;
992 case XML_SCHEMA_TYPE_EXTENSION:
993 fprintf(output, "extension ");
994 break;
995 default:
996 fprintf(output, "unknowntype%d ", type->type);
997 break;
998 }
999 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001000 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +00001001 }
1002 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001003 case XML_SCHEMA_CONTENT_UNKNOWN:
1004 fprintf(output, "unknown ");
1005 break;
1006 case XML_SCHEMA_CONTENT_EMPTY:
1007 fprintf(output, "empty ");
1008 break;
1009 case XML_SCHEMA_CONTENT_ELEMENTS:
1010 fprintf(output, "element ");
1011 break;
1012 case XML_SCHEMA_CONTENT_MIXED:
1013 fprintf(output, "mixed ");
1014 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00001015 /* Removed, since not used. */
1016 /*
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001017 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
1018 fprintf(output, "mixed_or_elems ");
1019 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00001020 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001021 case XML_SCHEMA_CONTENT_BASIC:
1022 fprintf(output, "basic ");
1023 break;
1024 case XML_SCHEMA_CONTENT_SIMPLE:
1025 fprintf(output, "simple ");
1026 break;
1027 case XML_SCHEMA_CONTENT_ANY:
1028 fprintf(output, "any ");
1029 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00001030 }
1031 fprintf(output, "\n");
1032 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001033 fprintf(output, " ");
1034 if (type->minOccurs != 1)
1035 fprintf(output, "min: %d ", type->minOccurs);
1036 if (type->maxOccurs >= UNBOUNDED)
1037 fprintf(output, "max: unbounded\n");
1038 else if (type->maxOccurs != 1)
1039 fprintf(output, "max: %d\n", type->maxOccurs);
1040 else
1041 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00001042 }
1043 if (type->annot != NULL)
1044 xmlSchemaAnnotDump(output, type->annot);
1045 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001046 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00001047
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001048 fprintf(output, " subtypes: ");
1049 while (sub != NULL) {
1050 fprintf(output, "%s ", sub->name);
1051 sub = sub->next;
1052 }
1053 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00001054 }
1055
1056}
1057
1058/**
1059 * xmlSchemaDump:
1060 * @output: the file output
1061 * @schema: a schema structure
1062 *
1063 * Dump a Schema structure.
1064 */
1065void
1066xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
1067{
1068 if (schema == NULL) {
1069 fprintf(output, "Schemas: NULL\n");
1070 return;
1071 }
1072 fprintf(output, "Schemas: ");
1073 if (schema->name != NULL)
1074 fprintf(output, "%s, ", schema->name);
1075 else
1076 fprintf(output, "no name, ");
1077 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001078 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001079 else
1080 fprintf(output, "no target namespace");
1081 fprintf(output, "\n");
1082 if (schema->annot != NULL)
1083 xmlSchemaAnnotDump(output, schema->annot);
1084
1085 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
1086 output);
1087 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001088 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00001089}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001090#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00001091
1092/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001093 * *
1094 * Utilities *
1095 * *
1096 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001097
Daniel Veillard01fa6152004-06-29 17:04:39 +00001098xmlAttrPtr
1099xmlSchemaGetPropNode(xmlNodePtr node, const xmlChar *name)
1100{
1101 xmlAttrPtr prop;
1102
1103 if ((node == NULL) || (name == NULL)) return(NULL);
1104 prop = node->properties;
1105 while (prop != NULL) {
1106 if ((xmlStrEqual(prop->name, name)) &&
1107 (prop->ns == NULL))
1108 return(prop);
1109 prop = prop->next;
1110 }
1111 return (NULL);
1112}
1113
1114static const xmlChar *
1115xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1116{
1117 xmlChar *val;
1118 const xmlChar *ret;
1119
1120 val = xmlNodeGetContent(node);
1121 if (val == NULL)
1122 return(NULL);
1123 ret = xmlDictLookup(ctxt->dict, val, -1);
1124 xmlFree(val);
1125 return(ret);
1126}
1127
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001128/**
1129 * xmlSchemaGetProp:
1130 * @ctxt: the parser context
1131 * @node: the node
1132 * @name: the property name
1133 *
1134 * Read a attribute value and internalize the string
1135 *
1136 * Returns the string or NULL if not present.
1137 */
1138static const xmlChar *
1139xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1140 const char *name)
1141{
1142 xmlChar *val;
1143 const xmlChar *ret;
1144
1145 val = xmlGetProp(node, BAD_CAST name);
1146 if (val == NULL)
1147 return(NULL);
1148 ret = xmlDictLookup(ctxt->dict, val, -1);
1149 xmlFree(val);
1150 return(ret);
1151}
1152
William M. Brack29aa7722004-05-12 00:27:56 +00001153#if 0
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001154/**
1155 * xmlSchemaGetNamespace:
1156 * @ctxt: the parser context
1157 * @schema: the schemas containing the declaration
1158 * @node: the node
1159 * @qname: the QName to analyze
1160 *
1161 * Find the namespace name for the given declaration.
1162 *
1163 * Returns the local name for that declaration, as well as the namespace name
William M. Bracke7091952004-05-11 15:09:58 +00001164 * NOTE: This function is no longer used (Buchcik, May '04)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001165 */
1166static const xmlChar *
1167xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1168 xmlNodePtr node, const xmlChar *qname,
1169 const xmlChar **namespace) {
1170 int len;
1171 const xmlChar *name, *prefix, *def = NULL;
1172 xmlNsPtr ns;
1173
1174 *namespace = NULL;
1175
William M. Bracke7091952004-05-11 15:09:58 +00001176 /* TODO: The following seems to be not correct here:
1177 * 1. The name of a declaration is a NCName, not a QName.
1178 * 2. The attribute "targetNamespace" is allowed for the
1179 * <schema> Element Information Item only.
1180 * 3. One cannot evaluate the target namespace, by the type
1181 * of declaration, since it is dependant on the xxxFormDefault
1182 * of <schema> and the form attribute of an <element> or <attribute>.
1183 */
1184
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001185 if (xmlStrEqual(node->name, BAD_CAST "element") ||
1186 xmlStrEqual(node->name, BAD_CAST "attribute") ||
1187 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
1188 xmlStrEqual(node->name, BAD_CAST "complexType")) {
1189 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
1190 }
1191
William M. Bracke7091952004-05-11 15:09:58 +00001192
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001193 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
1194 name = xmlSplitQName3(qname, &len);
1195 if (name == NULL) {
1196 if (def == NULL) {
1197 if (xmlStrEqual(node->name, BAD_CAST "element")) {
1198 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
1199 *namespace = schema->targetNamespace;
1200 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
1201 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
1202 *namespace = schema->targetNamespace;
1203 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
1204 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
1205 *namespace = schema->targetNamespace;
1206 }
1207 } else {
1208 *namespace = def;
1209 }
1210 return(qname);
1211 }
William M. Bracke7091952004-05-11 15:09:58 +00001212
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001213 name = xmlDictLookup(ctxt->dict, name, -1);
1214 prefix = xmlDictLookup(ctxt->dict, qname, len);
1215 if (def != NULL) {
1216 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
1217 "%s: presence of both prefix %s and targetNamespace\n",
1218 node->name, prefix);
1219 }
1220 ns = xmlSearchNs(node->doc, node, prefix);
1221 if (ns == NULL) {
1222 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1223 "%s: the QName prefix %s is undefined\n",
1224 node->name, prefix);
1225 return(name);
1226 }
1227 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1228 return(name);
1229}
William M. Brack29aa7722004-05-12 00:27:56 +00001230#endif
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001231
1232/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00001233 * *
1234 * Parsing functions *
1235 * *
1236 ************************************************************************/
1237
1238/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001239 * xmlSchemaGetElem:
1240 * @schema: the schemas context
1241 * @name: the element name
1242 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001243 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001244 *
1245 * Lookup a an element in the schemas or the accessible schemas
1246 *
1247 * Returns the element definition or NULL if not found.
1248 */
1249static xmlSchemaElementPtr
1250xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001251 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001252{
1253 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001254 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001255
1256 if ((name == NULL) || (schema == NULL))
1257 return (NULL);
1258
Daniel Veillard3646d642004-06-02 19:19:14 +00001259
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001260 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001261 if ((ret != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00001262 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_GLOBAL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001263 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00001264 } else
1265 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00001266 /*
1267 * This one was removed, since top level element declarations have
1268 * the target namespace specified in targetNamespace of the <schema>
1269 * information element, even if elementFormDefault is "unqualified".
1270 */
1271
1272 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001273 if (xmlStrEqual(namespace, schema->targetNamespace))
1274 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1275 else
1276 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001277 if ((ret != NULL) &&
1278 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001279 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001280 }
William M. Bracke7091952004-05-11 15:09:58 +00001281 */
Daniel Veillard3646d642004-06-02 19:19:14 +00001282
1283 /* if (level > 0) */
1284 if (namespace == NULL)
1285 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1286 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001287 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001288 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00001289 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00001290 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
1291 return (ret);
1292 } else
1293 ret = NULL;
1294 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001295#ifdef DEBUG
1296 if (ret == NULL) {
1297 if (namespace == NULL)
1298 fprintf(stderr, "Unable to lookup type %s", name);
1299 else
1300 fprintf(stderr, "Unable to lookup type %s:%s", name,
1301 namespace);
1302 }
1303#endif
1304 return (ret);
1305}
1306
1307/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001308 * xmlSchemaGetType:
1309 * @schema: the schemas context
1310 * @name: the type name
1311 * @ns: the type namespace
1312 *
1313 * Lookup a type in the schemas or the predefined types
1314 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001315 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001316 */
1317static xmlSchemaTypePtr
1318xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001319 const xmlChar * namespace)
1320{
Daniel Veillard4255d502002-04-16 15:50:10 +00001321 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001322 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001323
1324 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001325 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001326 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001327 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001328 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001329 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001330 }
1331 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001332 if (ret != NULL)
1333 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00001334 if (namespace == NULL)
1335 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1336 else
Daniel Veillard1d913862003-11-21 00:28:39 +00001337 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001338 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00001339 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001340 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1341 return (ret);
1342 } else
1343 ret = NULL;
1344 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001345#ifdef DEBUG
1346 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001347 if (namespace == NULL)
1348 fprintf(stderr, "Unable to lookup type %s", name);
1349 else
1350 fprintf(stderr, "Unable to lookup type %s:%s", name,
1351 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001352 }
1353#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001354 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001355}
1356
Daniel Veillard3646d642004-06-02 19:19:14 +00001357/**
1358 * xmlSchemaGetAttribute:
1359 * @schema: the context of the schema
1360 * @name: the name of the attribute
1361 * @ns: the target namespace of the attribute
1362 *
1363 * Lookup a an attribute in the schema or imported schemas
1364 *
1365 * Returns the attribute declaration or NULL if not found.
1366 */
1367static xmlSchemaAttributePtr
1368xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
1369 const xmlChar * namespace)
1370{
1371 xmlSchemaAttributePtr ret;
1372 xmlSchemaImportPtr import = NULL;
1373
1374 if ((name == NULL) || (schema == NULL))
1375 return (NULL);
1376
1377
1378 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
1379 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
1380 return (ret);
1381 else
1382 ret = NULL;
1383 if (namespace == NULL)
1384 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1385 else
1386 import = xmlHashLookup(schema->schemasImports, namespace);
1387 if (import != NULL) {
1388 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
1389 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
1390 return (ret);
1391 } else
1392 ret = NULL;
1393 }
1394#ifdef DEBUG
1395 if (ret == NULL) {
1396 if (namespace == NULL)
1397 fprintf(stderr, "Unable to lookup attribute %s", name);
1398 else
1399 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
1400 namespace);
1401 }
1402#endif
1403 return (ret);
1404}
1405
1406/**
1407 * xmlSchemaGetAttributeGroup:
1408 * @schema: the context of the schema
1409 * @name: the name of the attribute group
1410 * @ns: the target namespace of the attribute group
1411 *
1412 * Lookup a an attribute group in the schema or imported schemas
1413 *
1414 * Returns the attribute group definition or NULL if not found.
1415 */
1416static xmlSchemaAttributeGroupPtr
1417xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
1418 const xmlChar * namespace)
1419{
1420 xmlSchemaAttributeGroupPtr ret;
1421 xmlSchemaImportPtr import = NULL;
1422
1423 if ((name == NULL) || (schema == NULL))
1424 return (NULL);
1425
1426
1427 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
1428 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
1429 return (ret);
1430 else
1431 ret = NULL;
1432 if (namespace == NULL)
1433 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1434 else
1435 import = xmlHashLookup(schema->schemasImports, namespace);
1436 if (import != NULL) {
1437 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
1438 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
1439 return (ret);
1440 else
1441 ret = NULL;
1442 }
1443#ifdef DEBUG
1444 if (ret == NULL) {
1445 if (namespace == NULL)
1446 fprintf(stderr, "Unable to lookup attribute group %s", name);
1447 else
1448 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
1449 namespace);
1450 }
1451#endif
1452 return (ret);
1453}
1454
1455/**
1456 * xmlSchemaGetGroup:
1457 * @schema: the context of the schema
1458 * @name: the name of the group
1459 * @ns: the target namespace of the group
1460 *
1461 * Lookup a group in the schema or imported schemas
1462 *
1463 * Returns the group definition or NULL if not found.
1464 */
1465static xmlSchemaTypePtr
1466xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
1467 const xmlChar * namespace)
1468{
1469 xmlSchemaTypePtr ret;
1470 xmlSchemaImportPtr import = NULL;
1471
1472 if ((name == NULL) || (schema == NULL))
1473 return (NULL);
1474
1475
1476 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
1477 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
1478 return (ret);
1479 else
1480 ret = NULL;
1481 if (namespace == NULL)
1482 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1483 else
1484 import = xmlHashLookup(schema->schemasImports, namespace);
1485 if (import != NULL) {
1486 ret = xmlSchemaGetGroup(import->schema, name, namespace);
1487 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
1488 return (ret);
1489 else
1490 ret = NULL;
1491 }
1492#ifdef DEBUG
1493 if (ret == NULL) {
1494 if (namespace == NULL)
1495 fprintf(stderr, "Unable to lookup group %s", name);
1496 else
1497 fprintf(stderr, "Unable to lookup group %s:%s", name,
1498 namespace);
1499 }
1500#endif
1501 return (ret);
1502}
1503
Daniel Veillard4255d502002-04-16 15:50:10 +00001504/************************************************************************
1505 * *
1506 * Parsing functions *
1507 * *
1508 ************************************************************************/
1509
1510#define IS_BLANK_NODE(n) \
1511 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1512
1513/**
1514 * xmlSchemaIsBlank:
1515 * @str: a string
1516 *
1517 * Check if a string is ignorable
1518 *
1519 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1520 */
1521static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001522xmlSchemaIsBlank(xmlChar * str)
1523{
Daniel Veillard4255d502002-04-16 15:50:10 +00001524 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001525 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001526 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001527 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001528 return (0);
1529 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001530 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001531 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001532}
1533
1534/**
1535 * xmlSchemaAddNotation:
1536 * @ctxt: a schema validation context
1537 * @schema: the schema being built
1538 * @name: the item name
1539 *
1540 * Add an XML schema Attrribute declaration
1541 * *WARNING* this interface is highly subject to change
1542 *
1543 * Returns the new struture or NULL in case of error
1544 */
1545static xmlSchemaNotationPtr
1546xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001547 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001548{
1549 xmlSchemaNotationPtr ret = NULL;
1550 int val;
1551
1552 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1553 return (NULL);
1554
1555 if (schema->notaDecl == NULL)
1556 schema->notaDecl = xmlHashCreate(10);
1557 if (schema->notaDecl == NULL)
1558 return (NULL);
1559
1560 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1561 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001562 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001563 return (NULL);
1564 }
1565 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001566 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001567 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1568 ret);
1569 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001570 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1571 XML_SCHEMAP_REDEFINED_NOTATION,
1572 "Notation %s already defined\n",
1573 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001574 xmlFree(ret);
1575 return (NULL);
1576 }
1577 return (ret);
1578}
1579
1580
1581/**
1582 * xmlSchemaAddAttribute:
1583 * @ctxt: a schema validation context
1584 * @schema: the schema being built
1585 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001586 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001587 *
1588 * Add an XML schema Attrribute declaration
1589 * *WARNING* this interface is highly subject to change
1590 *
1591 * Returns the new struture or NULL in case of error
1592 */
1593static xmlSchemaAttributePtr
1594xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001595 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001596{
1597 xmlSchemaAttributePtr ret = NULL;
1598 int val;
1599
1600 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1601 return (NULL);
1602
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001603#ifdef DEBUG
1604 fprintf(stderr, "Adding attribute %s\n", name);
1605 if (namespace != NULL)
1606 fprintf(stderr, " target namespace %s\n", namespace);
1607#endif
1608
Daniel Veillard4255d502002-04-16 15:50:10 +00001609 if (schema->attrDecl == NULL)
1610 schema->attrDecl = xmlHashCreate(10);
1611 if (schema->attrDecl == NULL)
1612 return (NULL);
1613
1614 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1615 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001616 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001617 return (NULL);
1618 }
1619 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001620 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1621 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001622 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001623 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001624 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001625 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1626 XML_SCHEMAP_REDEFINED_ATTR,
1627 "Attribute %s already defined\n",
1628 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001629 xmlFree(ret);
1630 return (NULL);
1631 }
1632 return (ret);
1633}
1634
1635/**
1636 * xmlSchemaAddAttributeGroup:
1637 * @ctxt: a schema validation context
1638 * @schema: the schema being built
1639 * @name: the item name
1640 *
1641 * Add an XML schema Attrribute Group declaration
1642 *
1643 * Returns the new struture or NULL in case of error
1644 */
1645static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001646xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1647 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001648{
1649 xmlSchemaAttributeGroupPtr ret = NULL;
1650 int val;
1651
1652 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1653 return (NULL);
1654
1655 if (schema->attrgrpDecl == NULL)
1656 schema->attrgrpDecl = xmlHashCreate(10);
1657 if (schema->attrgrpDecl == NULL)
1658 return (NULL);
1659
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001660 ret =
1661 (xmlSchemaAttributeGroupPtr)
1662 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001663 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001664 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001665 return (NULL);
1666 }
1667 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001668 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001669 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001670 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001671 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001672 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1673 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1674 "Attribute group %s already defined\n",
1675 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001676 xmlFree(ret);
1677 return (NULL);
1678 }
1679 return (ret);
1680}
1681
1682/**
1683 * xmlSchemaAddElement:
1684 * @ctxt: a schema validation context
1685 * @schema: the schema being built
1686 * @name: the type name
1687 * @namespace: the type namespace
1688 *
1689 * Add an XML schema Element declaration
1690 * *WARNING* this interface is highly subject to change
1691 *
1692 * Returns the new struture or NULL in case of error
1693 */
1694static xmlSchemaElementPtr
1695xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1696 const xmlChar * name, const xmlChar * namespace)
1697{
1698 xmlSchemaElementPtr ret = NULL;
1699 int val;
1700
1701 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1702 return (NULL);
1703
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001704#ifdef DEBUG
1705 fprintf(stderr, "Adding element %s\n", name);
1706 if (namespace != NULL)
1707 fprintf(stderr, " target namespace %s\n", namespace);
1708#endif
1709
Daniel Veillard4255d502002-04-16 15:50:10 +00001710 if (schema->elemDecl == NULL)
1711 schema->elemDecl = xmlHashCreate(10);
1712 if (schema->elemDecl == NULL)
1713 return (NULL);
1714
1715 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1716 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001717 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001718 return (NULL);
1719 }
1720 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001721 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1722 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001723 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001724 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001725 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001726 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001727
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001728 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001729 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1730 namespace, ret);
1731 if (val != 0) {
1732 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1733 XML_SCHEMAP_REDEFINED_ELEMENT,
1734 "Element %s already defined\n",
1735 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001736 xmlFree(ret);
1737 return (NULL);
1738 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001739 }
1740 return (ret);
1741}
1742
1743/**
1744 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001745 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00001746 * @schema: the schema being built
1747 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001748 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001749 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001750 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00001751 * *WARNING* this interface is highly subject to change
1752 *
1753 * Returns the new struture or NULL in case of error
1754 */
1755static xmlSchemaTypePtr
1756xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001757 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001758{
1759 xmlSchemaTypePtr ret = NULL;
1760 int val;
1761
1762 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1763 return (NULL);
1764
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001765#ifdef DEBUG
1766 fprintf(stderr, "Adding type %s\n", name);
1767 if (namespace != NULL)
1768 fprintf(stderr, " target namespace %s\n", namespace);
1769#endif
1770
Daniel Veillard4255d502002-04-16 15:50:10 +00001771 if (schema->typeDecl == NULL)
1772 schema->typeDecl = xmlHashCreate(10);
1773 if (schema->typeDecl == NULL)
1774 return (NULL);
1775
1776 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1777 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001778 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001779 return (NULL);
1780 }
1781 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001782 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001783 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001784 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001785 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001786 if (ctxt->includes == 0) {
1787 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1788 XML_SCHEMAP_REDEFINED_TYPE,
1789 "Type %s already defined\n",
1790 name, NULL);
1791 xmlFree(ret);
1792 return (NULL);
1793 } else {
1794 xmlSchemaTypePtr prev;
1795
1796 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1797 if (prev == NULL) {
1798 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1799 XML_ERR_INTERNAL_ERROR,
1800 "Internal error on type %s definition\n",
1801 name, NULL);
1802 xmlFree(ret);
1803 return (NULL);
1804 }
1805 ret->redef = prev->redef;
1806 prev->redef = ret;
1807 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001808 }
1809 ret->minOccurs = 1;
1810 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00001811 ret->attributeUses = NULL;
1812 ret->attributeWildcard = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001813
1814 return (ret);
1815}
1816
1817/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00001818 * xmlSchemaNewItemInternal:
1819 * @ctxt: the schema parser context
1820 * @name: the internal name of the restriction
1821 *
1822 * Createa an schema item
1823 *
1824 * Returns the new structure or NULL in case of an error.
1825 */
1826static xmlSchemaTypePtr
1827xmlSchemaNewItemInternal(xmlSchemaParserCtxtPtr ctxt,
1828 const xmlChar * name)
1829{
1830 xmlSchemaTypePtr ret = NULL;
1831
1832 if ((ctxt == NULL) || (name == NULL))
1833 return (NULL);
1834
1835#ifdef DEBUG
1836 fprintf(stderr, "Creating item %s\n", name);
1837#endif
1838 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1839 if (ret == NULL) {
1840 xmlSchemaPErrMemory(ctxt, "allocating item", NULL);
1841 return (NULL);
1842 }
1843 memset(ret, 0, sizeof(xmlSchemaType));
1844 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1845 ret->minOccurs = 1;
1846 ret->maxOccurs = 1;
1847
1848 return (ret);
1849}
1850
1851/**
1852 * xmlSchemaNewRestriction:
1853 * @ctxt: the schema parser context
1854 * @name: the internal name of the restriction
1855 *
1856 * Create a <restriction> item
1857 *
1858 * Returns the new structure or NULL in case of an error.
1859 */
1860static xmlSchemaTypePtr
1861xmlSchemaNewRestriction(xmlSchemaParserCtxtPtr ctxt,
1862 const xmlChar * name)
1863{
1864 xmlSchemaTypePtr ret;
1865
1866 ret = xmlSchemaNewItemInternal(ctxt, name);
1867 if (ret != NULL)
1868 ret->type = XML_SCHEMA_TYPE_RESTRICTION;
1869
1870 return (ret);
1871}
1872
1873/**
1874 * xmlSchemaNewExtension:
1875 * @ctxt: the schema parser context
1876 * @name: the internal name of the extension
1877 *
1878 * Create an <extension> item
1879 *
1880 * Returns the new structure or NULL in case of an error.
1881 */
1882static xmlSchemaTypePtr
1883xmlSchemaNewExtension(xmlSchemaParserCtxtPtr ctxt,
1884 const xmlChar * name)
1885{
1886 xmlSchemaTypePtr ret;
1887
1888 ret = xmlSchemaNewItemInternal(ctxt, name);
1889 if (ret != NULL)
1890 ret->type = XML_SCHEMA_TYPE_EXTENSION;
1891
1892 return (ret);
1893}
1894
1895/**
1896 * xmlSchemaNewSimpleContent:
1897 * @ctxt: the schema parser context
1898 * @name: the internal name of the simpleContent
1899 *
1900 * Create a <simpleContent> item
1901 *
1902 * Returns the new structure or NULL in case of an error.
1903 */
1904static xmlSchemaTypePtr
1905xmlSchemaNewSimpleContent(xmlSchemaParserCtxtPtr ctxt,
1906 const xmlChar * name)
1907{
1908 xmlSchemaTypePtr ret;
1909
1910 ret = xmlSchemaNewItemInternal(ctxt, name);
1911 if (ret != NULL)
1912 ret->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
1913
1914 return (ret);
1915}
1916
1917/**
1918 * xmlSchemaNewComplexContent:
1919 * @ctxt: the schema parser context
1920 * @name: the internal name of the complexContent
1921 *
1922 * Create a <complexContent> item
1923 *
1924 * Returns the new structure or NULL in case of an error.
1925 */
1926static xmlSchemaTypePtr
1927xmlSchemaNewComplexContent(xmlSchemaParserCtxtPtr ctxt,
1928 const xmlChar * name)
1929{
1930 xmlSchemaTypePtr ret;
1931
1932 ret = xmlSchemaNewItemInternal(ctxt, name);
1933 if (ret != NULL)
1934 ret->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
1935
1936 return (ret);
1937}
1938
1939/**
1940 * xmlSchemaNewUnion:
1941 * @ctxt: the schema parser context
1942 * @name: the internal name of the union
1943 *
1944 * Create an <union> item
1945 * *WARNING* this interface is highly subject to change
1946 *
1947 * Returns the new structure or NULL in case of an error.
1948 */
1949static xmlSchemaTypePtr
1950xmlSchemaNewUnion(xmlSchemaParserCtxtPtr ctxt,
1951 const xmlChar * name)
1952{
1953 xmlSchemaTypePtr ret;
1954
1955 ret = xmlSchemaNewItemInternal(ctxt, name);
1956 if (ret != NULL)
1957 ret->type = XML_SCHEMA_TYPE_UNION;
1958
1959 return (ret);
1960}
1961
1962/**
1963 * xmlSchemaNewList:
1964 * @ctxt: the schema parser context
1965 * @name: the internal name of the union
1966 *
1967 * Create an <union> item
1968 * *WARNING* this interface is highly subject to change
1969 *
1970 * Returns the new structure or NULL in case of an error.
1971 */
1972static xmlSchemaTypePtr
1973xmlSchemaNewList(xmlSchemaParserCtxtPtr ctxt,
1974 const xmlChar * name)
1975{
1976 xmlSchemaTypePtr ret;
1977
1978 ret = xmlSchemaNewItemInternal(ctxt, name);
1979 if (ret != NULL)
1980 ret->type = XML_SCHEMA_TYPE_LIST;
1981
1982 return (ret);
1983}
1984
1985/**
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001986 * xmlSchemaAddGroup:
1987 * @ctxt: a schema validation context
1988 * @schema: the schema being built
1989 * @name: the group name
1990 *
1991 * Add an XML schema Group definition
1992 *
1993 * Returns the new struture or NULL in case of error
1994 */
1995static xmlSchemaTypePtr
1996xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001997 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001998{
1999 xmlSchemaTypePtr ret = NULL;
2000 int val;
2001
2002 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2003 return (NULL);
2004
2005 if (schema->groupDecl == NULL)
2006 schema->groupDecl = xmlHashCreate(10);
2007 if (schema->groupDecl == NULL)
2008 return (NULL);
2009
2010 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
2011 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002012 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002013 return (NULL);
2014 }
2015 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002016 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002017 val =
2018 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
2019 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002020 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002021 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
2022 XML_SCHEMAP_REDEFINED_GROUP,
2023 "Group %s already defined\n",
2024 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002025 xmlFree(ret);
2026 return (NULL);
2027 }
2028 ret->minOccurs = 1;
2029 ret->maxOccurs = 1;
2030
2031 return (ret);
2032}
2033
Daniel Veillard3646d642004-06-02 19:19:14 +00002034/**
2035 * xmlSchemaNewWildcardNs:
2036 * @ctxt: a schema validation context
2037 *
2038 * Creates a new wildcard namespace constraint.
2039 *
2040 * Returns the new struture or NULL in case of error
2041 */
2042static xmlSchemaWildcardNsPtr
2043xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
2044{
2045 xmlSchemaWildcardNsPtr ret;
2046
2047 ret = (xmlSchemaWildcardNsPtr)
2048 xmlMalloc(sizeof(xmlSchemaWildcardNs));
2049 if (ret == NULL) {
2050 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
2051 return (NULL);
2052 }
2053 ret->value = NULL;
2054 ret->next = NULL;
2055 return (ret);
2056}
2057
2058/**
2059 * xmlSchemaAddWildcard:
2060 * @ctxt: a schema validation context
2061 * @schema: the schema being built
2062 * @name: the group name
2063 *
2064 * Add an XML schema Group definition
2065 *
2066 * Returns the new struture or NULL in case of error
2067 */
2068static xmlSchemaWildcardPtr
2069xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
2070{
2071 xmlSchemaWildcardPtr ret = NULL;
2072
2073 if (ctxt == NULL)
2074 return (NULL);
2075
2076 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
2077 if (ret == NULL) {
2078 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
2079 return (NULL);
2080 }
2081 memset(ret, 0, sizeof(xmlSchemaWildcard));
2082 ret->minOccurs = 1;
2083 ret->maxOccurs = 1;
2084
2085 return (ret);
2086}
2087
Daniel Veillard4255d502002-04-16 15:50:10 +00002088/************************************************************************
2089 * *
2090 * Utilities for parsing *
2091 * *
2092 ************************************************************************/
2093
2094/**
2095 * xmlGetQNameProp:
2096 * @ctxt: a schema validation context
2097 * @node: a subtree containing XML Schema informations
2098 * @name: the attribute name
2099 * @namespace: the result namespace if any
2100 *
2101 * Extract a QName Attribute value
2102 *
2103 * Returns the NCName or NULL if not found, and also update @namespace
2104 * with the namespace URI
2105 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002106static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00002107xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002108 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002109{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002110 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00002111 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002112 const xmlChar *ret, *prefix;
2113 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00002114
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002115 *namespace = NULL;
2116 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002117 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002118 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002119
Daniel Veillardba0153a2004-04-01 10:42:31 +00002120 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00002121 ns = xmlSearchNs(node->doc, node, 0);
2122 if (ns) {
2123 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
2124 return (val);
2125 }
2126 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002127 ret = xmlSplitQName3(val, &len);
2128 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002129 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002130 }
2131 ret = xmlDictLookup(ctxt->dict, ret, -1);
2132 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00002133
2134 ns = xmlSearchNs(node->doc, node, prefix);
2135 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002136 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
Daniel Veillard01fa6152004-06-29 17:04:39 +00002137 "Attribute \"%s\": the QName prefix \"%s\" is undefined\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002138 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00002139 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002140 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002141 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002142 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002143}
2144
2145/**
2146 * xmlGetMaxOccurs:
2147 * @ctxt: a schema validation context
2148 * @node: a subtree containing XML Schema informations
2149 *
2150 * Get the maxOccurs property
2151 *
2152 * Returns the default if not found, or the value
2153 */
2154static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002155xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2156{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002157 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00002158 int ret = 0;
2159
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002160 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00002161 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002162 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002163
2164 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002165 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00002166 }
2167
2168 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00002169 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002170 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002171 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002172 ret = ret * 10 + (*cur - '0');
2173 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002174 }
William M. Brack76e95df2003-10-18 16:20:14 +00002175 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002176 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002177 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002178 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2179 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002180 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002181 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002182 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002183}
2184
2185/**
2186 * xmlGetMinOccurs:
2187 * @ctxt: a schema validation context
2188 * @node: a subtree containing XML Schema informations
2189 *
2190 * Get the minOccurs property
2191 *
2192 * Returns the default if not found, or the value
2193 */
2194static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002195xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2196{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002197 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00002198 int ret = 0;
2199
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002200 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00002201 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002202 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002203
2204 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00002205 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002206 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002207 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002208 ret = ret * 10 + (*cur - '0');
2209 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002210 }
William M. Brack76e95df2003-10-18 16:20:14 +00002211 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002212 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002213 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002214 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2215 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002216 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002217 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002218 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002219}
2220
2221/**
2222 * xmlGetBooleanProp:
2223 * @ctxt: a schema validation context
2224 * @node: a subtree containing XML Schema informations
2225 * @name: the attribute name
2226 * @def: the default value
2227 *
2228 * Get is a bolean property is set
2229 *
2230 * Returns the default if not found, 0 if found to be false,
2231 * 1 if found to be true
2232 */
2233static int
2234xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002235 const char *name, int def)
2236{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002237 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00002238
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002239 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002240 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002241 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00002242
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002243 if (xmlStrEqual(val, BAD_CAST "true"))
2244 def = 1;
2245 else if (xmlStrEqual(val, BAD_CAST "false"))
2246 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00002247 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002248 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
2249 "Attribute %s: the value %s is not boolean\n",
2250 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002251 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002252 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00002253}
2254
2255/************************************************************************
2256 * *
2257 * Shema extraction from an Infoset *
2258 * *
2259 ************************************************************************/
2260static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
2261 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00002262 xmlNodePtr node,
2263 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002264static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
2265 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00002266 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00002267 xmlNodePtr node,
2268 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002269static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
2270 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00002271 xmlSchemaPtr schema,
2272 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002273 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00002274static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
2275 xmlSchemaPtr schema,
2276 xmlNodePtr node);
2277static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
2278 xmlSchemaPtr schema,
2279 xmlNodePtr node);
2280static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
2281 ctxt,
2282 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002283 xmlNodePtr node,
2284 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002285static xmlSchemaAttributeGroupPtr
2286xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00002287 xmlSchemaPtr schema, xmlNodePtr node,
2288 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002289static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
2290 xmlSchemaPtr schema,
2291 xmlNodePtr node);
2292static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
2293 xmlSchemaPtr schema,
2294 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00002295static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002296xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
2297 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002298
2299/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002300 * xmlSchemaParseSchemaAttrValue:
2301 *
2302 * @ctxt: a schema parser context
2303 * @attr: the schema attribute being validated
2304 * @type: the built-in type to be validated against
2305 * @value: the value to be validated
2306 *
2307 * Validates a value against the given built-in type.
2308 * This one is intended to be used internally for validation
2309 * of schema attribute values during parsing of the schema.
2310 *
2311 * Returns 0 if the value is valid, a positive error code
2312 * number otherwise and -1 in case of an internal or API error.
2313 */
2314static int
2315xmlSchemaParseSchemaAttrValue(xmlSchemaParserCtxtPtr ctxt,
2316 xmlAttrPtr attr,
2317 xmlSchemaTypePtr type)
2318{
2319 const xmlChar *value;
2320 int ret;
2321
2322 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
2323 return (-1);
2324 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
2325 switch (type->builtInType) {
2326 case XML_SCHEMAS_NCNAME:
2327 ret = xmlValidateNCName(value, 1);
2328 break;
2329 case XML_SCHEMAS_QNAME:
2330 ret = xmlValidateQName(value, 1);
2331 if ((ret == 0) && (attr != NULL)) {
2332 xmlChar *uri = NULL;
2333 xmlChar *local = NULL;
2334 xmlChar *prefix;
2335
2336 local = xmlSplitQName2(value, &prefix);
2337 if (prefix != NULL) {
2338 xmlNsPtr ns;
2339
2340 ns = xmlSearchNs(attr->doc, (xmlNodePtr) attr, prefix);
2341 if (ns == NULL) {
2342 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
2343 XML_SCHEMAP_PREFIX_UNDEFINED,
2344 "Attribute \"%s\": the QName prefix "
2345 "\"%s\" is undefined.\n",
2346 attr->name, prefix);
2347 ret = 1;
2348 }
2349 }
2350 if (local != NULL)
2351 xmlFree(local);
2352 if (prefix != NULL)
2353 xmlFree(prefix);
2354 }
2355 break;
2356 default: {
2357 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
2358 XML_SCHEMAS_ERR_INTERNAL,
2359 "Internal error: xmlSchemaParseSchemaAttrValue, validation "
2360 "using this type in not implemented yet\"%s\".\n",
2361 type->name, NULL);
2362 return (-1);
2363 }
2364 }
2365 if (ret > 0) {
2366 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
2367 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr,
2368 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
2369 NULL, NULL, NULL,
2370 "The schema attribute \"%s\" with the value \"%s\" is not "
2371 "of built-in list simple type \"%s\".\n",
2372 attr->name, value, type->name, NULL, NULL);
2373 } else {
2374 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) {
2375 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr,
2376 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
2377 NULL, NULL, NULL,
2378 "The schema attribute \"%s\" with the value \"%s\" is not "
2379 "of built-in primitive type \"%s\".\n",
2380 attr->name, value, type->name, NULL, NULL);
2381 } else {
2382 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr,
2383 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
2384 NULL, NULL, NULL,
2385 "The schema attribute \"%s\" with the value \"%s\" is not "
2386 "of built-in atomic simple type \"%s\".\n",
2387 attr->name, value, type->name, NULL, NULL);
2388 }
2389 }
2390 }
2391 return (ret);
2392}
2393
2394/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002395 * xmlSchemaParseAttrDecls:
2396 * @ctxt: a schema validation context
2397 * @schema: the schema being built
2398 * @node: a subtree containing XML Schema informations
2399 * @type: the hosting type
2400 *
2401 * parse a XML schema attrDecls declaration corresponding to
2402 * <!ENTITY % attrDecls
2403 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
2404 */
2405static xmlNodePtr
2406xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2407 xmlNodePtr child, xmlSchemaTypePtr type)
2408{
2409 xmlSchemaAttributePtr lastattr, attr;
2410
2411 lastattr = NULL;
2412 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002413 (IS_SCHEMA(child, "attributeGroup"))) {
2414 attr = NULL;
2415 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00002416 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002417 } else if (IS_SCHEMA(child, "attributeGroup")) {
2418 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00002419 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002420 }
2421 if (attr != NULL) {
2422 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002423 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
2424 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
2425 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002426 type->attributes = attr;
2427 lastattr = attr;
2428 } else {
2429 lastattr->next = attr;
2430 lastattr = attr;
2431 }
2432 }
2433 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002434 }
2435 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002436 xmlSchemaWildcardPtr wildcard;
2437
2438 wildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
2439 if (wildcard != NULL) {
2440 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
2441 ((xmlSchemaAttributeGroupPtr) type)->attributeWildcard = wildcard;
2442 else
2443 type->attributeWildcard = wildcard;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002444 }
2445 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002446 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002447 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002448}
2449
2450/**
2451 * xmlSchemaParseAnnotation:
2452 * @ctxt: a schema validation context
2453 * @schema: the schema being built
2454 * @node: a subtree containing XML Schema informations
2455 *
2456 * parse a XML schema Attrribute declaration
2457 * *WARNING* this interface is highly subject to change
2458 *
William M. Bracke7091952004-05-11 15:09:58 +00002459 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002460 * 1 in case of success.
2461 */
2462static xmlSchemaAnnotPtr
2463xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2464 xmlNodePtr node)
2465{
2466 xmlSchemaAnnotPtr ret;
2467
2468 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2469 return (NULL);
2470 ret = xmlSchemaNewAnnot(ctxt, node);
2471
2472 return (ret);
2473}
2474
2475/**
2476 * xmlSchemaParseFacet:
2477 * @ctxt: a schema validation context
2478 * @schema: the schema being built
2479 * @node: a subtree containing XML Schema informations
2480 *
2481 * parse a XML schema Facet declaration
2482 * *WARNING* this interface is highly subject to change
2483 *
2484 * Returns the new type structure or NULL in case of error
2485 */
2486static xmlSchemaFacetPtr
2487xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002488 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002489{
2490 xmlSchemaFacetPtr facet;
2491 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002492 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00002493
2494 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2495 return (NULL);
2496
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002497 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002498 if (facet == NULL) {
2499 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
2500 return (NULL);
2501 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002502 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002503 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00002504 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002505 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
2506 "Facet %s has no value\n", node->name, NULL);
2507 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00002508 return (NULL);
2509 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002510 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002511 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002512 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002513 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002514 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002515 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002516 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002517 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002518 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002519 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002520 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002521 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002522 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002523 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002524 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002525 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002526 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002527 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002528 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002529 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002530 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002531 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
2532 } else if (IS_SCHEMA(node, "minLength")) {
2533 facet->type = XML_SCHEMA_FACET_MINLENGTH;
2534 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002535 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
2536 "Unknown facet type %s\n", node->name, NULL);
2537 xmlSchemaFreeFacet(facet);
2538 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002539 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002540 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002541 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00002542 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
2543 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
2544 const xmlChar *fixed;
2545
2546 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
2547 if (fixed != NULL) {
2548 if (xmlStrEqual(fixed, BAD_CAST "true"))
2549 facet->fixed = 1;
2550 }
2551 }
2552
Daniel Veillard4255d502002-04-16 15:50:10 +00002553 child = node->children;
2554
2555 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002556 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2557 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002558 }
2559 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002560 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
2561 "Facet %s has unexpected child content\n",
2562 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002563 }
2564 return (facet);
2565}
2566
2567/**
2568 * xmlSchemaParseAny:
2569 * @ctxt: a schema validation context
2570 * @schema: the schema being built
2571 * @node: a subtree containing XML Schema informations
2572 *
2573 * parse a XML schema Any declaration
2574 * *WARNING* this interface is highly subject to change
2575 *
2576 * Returns the new type structure or NULL in case of error
2577 */
2578static xmlSchemaTypePtr
2579xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2580 xmlNodePtr node)
2581{
2582 xmlSchemaTypePtr type;
2583 xmlNodePtr child = NULL;
2584 xmlChar name[30];
2585
2586 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2587 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002588 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002589 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002590 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002591 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002592 type->node = node;
2593 type->type = XML_SCHEMA_TYPE_ANY;
2594 child = node->children;
2595 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2596 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2597
2598 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002599 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2600 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002601 }
2602 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002603 xmlSchemaPErr2(ctxt, node, child,
2604 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
2605 "Sequence %s has unexpected content\n", type->name,
2606 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002607 }
2608
2609 return (type);
2610}
2611
2612/**
2613 * xmlSchemaParseNotation:
2614 * @ctxt: a schema validation context
2615 * @schema: the schema being built
2616 * @node: a subtree containing XML Schema informations
2617 *
2618 * parse a XML schema Notation declaration
2619 *
2620 * Returns the new structure or NULL in case of error
2621 */
2622static xmlSchemaNotationPtr
2623xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002624 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002625{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002626 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002627 xmlSchemaNotationPtr ret;
2628 xmlNodePtr child = NULL;
2629
2630 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2631 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002632 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002633 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002634 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
2635 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002636 return (NULL);
2637 }
2638 ret = xmlSchemaAddNotation(ctxt, schema, name);
2639 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002640 return (NULL);
2641 }
2642 child = node->children;
2643 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002644 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2645 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002646 }
2647 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002648 xmlSchemaPErr2(ctxt, node, child,
2649 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
2650 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002651 }
2652
2653 return (ret);
2654}
2655
2656/**
2657 * xmlSchemaParseAnyAttribute:
2658 * @ctxt: a schema validation context
2659 * @schema: the schema being built
2660 * @node: a subtree containing XML Schema informations
2661 *
2662 * parse a XML schema AnyAttrribute declaration
2663 * *WARNING* this interface is highly subject to change
2664 *
2665 * Returns an attribute def structure or NULL
2666 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002667static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002668xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
2669 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002670{
Daniel Veillard3646d642004-06-02 19:19:14 +00002671 const xmlChar *processContents, *nsConstraint, *end, *cur, *dictMember;
2672 xmlChar *member;
2673 xmlSchemaWildcardPtr ret;
2674 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002675 xmlNodePtr child = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002676
2677 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2678 return (NULL);
2679
Daniel Veillard3646d642004-06-02 19:19:14 +00002680 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00002681 if (ret == NULL) {
2682 return (NULL);
2683 }
William M. Bracke7091952004-05-11 15:09:58 +00002684 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002685 ret->id = xmlSchemaGetProp(ctxt, node, "id");
2686 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002687 if ((processContents == NULL)
2688 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00002689 ret->processContents = XML_SCHEMAS_ANY_STRICT;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002690 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00002691 ret->processContents = XML_SCHEMAS_ANY_SKIP;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002692 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00002693 ret->processContents = XML_SCHEMAS_ANY_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00002694 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00002695 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002696 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
William M. Bracke7091952004-05-11 15:09:58 +00002697 "anyAttribute has unexpected content "
2698 "for processContents: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002699 processContents, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002700 ret->processContents = XML_SCHEMAS_ANY_STRICT;
Daniel Veillard3646d642004-06-02 19:19:14 +00002701 }
2702 /*
2703 * Build the namespace constraints.
2704 */
2705 nsConstraint = xmlSchemaGetProp(ctxt, node, "namespace");
William M. Brack803812b2004-06-03 02:11:24 +00002706 if ((nsConstraint == NULL) || (xmlStrEqual(nsConstraint, BAD_CAST "##any")))
Daniel Veillard3646d642004-06-02 19:19:14 +00002707 ret->any = 1;
William M. Brack803812b2004-06-03 02:11:24 +00002708 else if (xmlStrEqual(nsConstraint, BAD_CAST "##other")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002709 ret->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
2710 if (ret->negNsSet == NULL) {
2711 xmlSchemaFreeWildcard(ret);
2712 return (NULL);
2713 }
2714 ret->negNsSet->value = schema->targetNamespace;
2715 } else {
2716 cur = nsConstraint;
2717 do {
2718 while (IS_BLANK_CH(*cur))
2719 cur++;
2720 end = cur;
2721 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
2722 end++;
2723 if (end == cur)
2724 break;
2725 member = xmlStrndup(cur, end - cur);
William M. Brack803812b2004-06-03 02:11:24 +00002726 if ((xmlStrEqual(member, BAD_CAST "##other")) ||
2727 (xmlStrEqual(member, BAD_CAST "##any"))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002728 xmlSchemaPErr(ctxt, ret->node, XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
2729 "The namespace constraint of an anyAttribute "
2730 "is a set and must not contain \"%s\"\n",
2731 member, NULL);
2732 } else {
2733 /*
2734 * TODO: Validate the value (anyURI).
2735 */
William M. Brack803812b2004-06-03 02:11:24 +00002736 if (xmlStrEqual(member, BAD_CAST "##targetNamespace")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002737 dictMember = schema->targetNamespace;
William M. Brack803812b2004-06-03 02:11:24 +00002738 } else if (xmlStrEqual(member, BAD_CAST "##local")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002739 dictMember = NULL;
2740 } else
2741 dictMember = xmlDictLookup(ctxt->dict, member, -1);
2742 /*
2743 * Avoid dublicate namespaces.
2744 */
2745 tmp = ret->nsSet;
2746 while (tmp != NULL) {
2747 if (dictMember == tmp->value)
2748 break;
2749 tmp = tmp->next;
2750 }
2751 if (tmp == NULL) {
2752 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
2753 if (tmp == NULL) {
2754 xmlFree(member);
2755 xmlSchemaFreeWildcard(ret);
2756 return (NULL);
2757 }
2758 tmp->value = dictMember;
2759 tmp->next = NULL;
2760 if (ret->nsSet == NULL)
2761 ret->nsSet = tmp;
2762 else
2763 lastNs->next = tmp;
2764 lastNs = tmp;
2765 }
2766
2767 }
2768 xmlFree(member);
2769 cur = end;
2770 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00002771 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002772
2773 child = node->children;
2774 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002775 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2776 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002777 }
2778 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002779 xmlSchemaPErr2(ctxt, node, child,
2780 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
Daniel Veillard3646d642004-06-02 19:19:14 +00002781 "anyAttribute has unexpected content\n",
2782 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002783 }
2784
2785 return (ret);
2786}
2787
2788
2789/**
2790 * xmlSchemaParseAttribute:
2791 * @ctxt: a schema validation context
2792 * @schema: the schema being built
2793 * @node: a subtree containing XML Schema informations
2794 *
2795 * parse a XML schema Attrribute declaration
2796 * *WARNING* this interface is highly subject to change
2797 *
William M. Bracke7091952004-05-11 15:09:58 +00002798 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002799 */
2800static xmlSchemaAttributePtr
2801xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002802 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002803{
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002804 const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal;
Daniel Veillard4255d502002-04-16 15:50:10 +00002805 xmlSchemaAttributePtr ret;
2806 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002807 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002808 int hasRefType = 0;
William M. Bracke7091952004-05-11 15:09:58 +00002809
2810 /*
2811 * Note that the w3c spec assumes the schema to be validated with schema
2812 * for schemas beforehand.
2813 *
2814 * 3.2.3 Constraints on XML Representations of Attribute Declarations
2815 *
2816 * TODO: Complete implementation of:
2817 * 3.2.6 Schema Component Constraint: Attribute Declaration Properties
2818 * Correct
2819 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002820
2821 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2822 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002823
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002824 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002825 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002826 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002827 /* 3.2.3 : 3.1
2828 * One of ref or name must be present, but not both
2829 */
2830 if (ref == NULL) {
2831 xmlSchemaPErr(ctxt, node,
2832 XML_SCHEMAP_ATTR_NONAME_NOREF,
2833 "Attribute declaration has no \"name\" or \"ref\"\n",
2834 NULL, NULL);
2835 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002836 }
William M. Bracke7091952004-05-11 15:09:58 +00002837 hasRefType = 1;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002838 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2839 name = (const xmlChar *) buf;
2840 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002841 if (!topLevel) {
2842 /* 3.2.3 : 3.2
2843 * If ref is present, then all of <simpleType>,
2844 * form and type must be absent.
2845 */
2846 if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2847 xmlSchemaPErr(ctxt, node,
2848 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2849 "Attribute declaration %s has \"ref\", thus "
2850 "\"form\" must be absent\n", name, NULL);
2851 }
2852 if (xmlSchemaGetProp(ctxt, node, "type") != NULL) {
2853 xmlSchemaPErr(ctxt, node,
2854 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2855 "Attribute declaration %s has \"ref\", thus "
2856 "\"type\" must be absent\n", name, NULL);
2857 }
2858 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002859 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002860 const xmlChar *ns = NULL;
2861 /* 3.2.3 : 3.1
2862 * One of ref or name must be present, but not both
2863 */
2864 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2865 xmlSchemaPErr(ctxt, node,
2866 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
Daniel Veillard3646d642004-06-02 19:19:14 +00002867 "Attribute declaration \"%s\" has both, \"name\" and "
2868 "\"ref\"\n", name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002869 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002870
William M. Bracke7091952004-05-11 15:09:58 +00002871 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2872 /* Evaluate the target namespace */
2873 if (schema->targetNamespace != NULL) {
2874 if (topLevel) {
2875 ns = schema->targetNamespace;
2876 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2877 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2878 BAD_CAST "qualified")) {
2879 ns = schema->targetNamespace;
2880 }
2881 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2882 ns = schema->targetNamespace;
2883 }
2884 }
2885 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns);
Daniel Veillard3646d642004-06-02 19:19:14 +00002886 if (ret == NULL)
2887 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002888 /* 3.2.6 Schema Component Constraint: xmlns Not Allowed */
2889 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2890 xmlSchemaPErr(ctxt, node,
2891 XML_SCHEMAP_INVALID_ATTR_NAME,
2892 "The name of an attribute declaration must not match "
2893 "\"xmlns\".\n", NULL, NULL);
2894 }
2895
2896 /* 3.2.6 Schema Component Constraint: xsi: Not Allowed */
2897 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
2898 xmlSchemaPErr(ctxt, node,
2899 XML_SCHEMAP_INVALID_ATTR_NAME,
2900 "The target namespace of an attribute declaration, "
2901 "must not match \"http://www.w3.org/2001/"
2902 "XMLSchema-instance\"", NULL, NULL);
2903 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002904 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002905 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002906 return (NULL);
2907 }
William M. Bracke7091952004-05-11 15:09:58 +00002908 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Daniel Veillard3646d642004-06-02 19:19:14 +00002909 if (topLevel)
2910 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
William M. Bracke7091952004-05-11 15:09:58 +00002911
2912 /* Handle the "use" attribute. */
2913 attrVal = xmlSchemaGetProp(ctxt, node, "use");
2914 if (attrVal != NULL) {
2915 if (xmlStrEqual(attrVal, BAD_CAST "optional"))
2916 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2917 else if (xmlStrEqual(attrVal, BAD_CAST "prohibited"))
2918 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
2919 else if (xmlStrEqual(attrVal, BAD_CAST "required"))
2920 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
2921 else
2922 xmlSchemaPErr(ctxt, node,
2923 XML_SCHEMAP_INVALID_ATTR_USE,
2924 "Attribute declaration %s has an invalid "
2925 "value for \"use\"\n", name, NULL);
2926 } else
2927 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002928
William M. Bracke7091952004-05-11 15:09:58 +00002929
2930 if (xmlSchemaGetProp(ctxt, node, "default") != NULL) {
2931 /* 3.2.3 : 1
2932 * default and fixed must not both be present.
2933 */
2934 if (xmlSchemaGetProp(ctxt, node, "fixed") != NULL) {
2935 xmlSchemaPErr(ctxt, node,
2936 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2937 "Attribute declaration has both, \"default\" "
2938 "and \"fixed\"\n", NULL, NULL);
2939 }
2940 /* 3.2.3 : 2
2941 * If default and use are both present, use must have
2942 * the actual value optional.
2943 */
2944 if (ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) {
2945 xmlSchemaPErr(ctxt, node,
2946 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2947 "Attribute declaration has \"default\" but "
2948 "\"use\" is not \"optional\"\n", NULL, NULL);
2949 }
2950 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002951
Daniel Veillard4255d502002-04-16 15:50:10 +00002952 ret->ref = ref;
2953 ret->refNs = refNs;
William M. Bracke7091952004-05-11 15:09:58 +00002954 /*
2955 * The setting of XML_SCHEMAS_ATTR_NSDEFAULT is not needed anymore,
2956 * since the target namespace was already evaluated and took
2957 * attributeFormDefault into account.
2958 */
2959 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002960 if ((ret->targetNamespace != NULL) &&
2961 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2962 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2963 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
William M. Bracke7091952004-05-11 15:09:58 +00002964 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002965 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
William M. Bracke7091952004-05-11 15:09:58 +00002966 if (ret->typeName != NULL)
2967 hasRefType = 1;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002968 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002969 child = node->children;
2970 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002971 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2972 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002973 }
2974 if (IS_SCHEMA(child, "simpleType")) {
William M. Bracke7091952004-05-11 15:09:58 +00002975 if (hasRefType) {
2976 /* 3.2.3 : 4
2977 * type and <simpleType> must not both be present.
2978 *
2979 * TODO: XML_SCHEMAP_INVALID_ATTR_COMBINATION seems not to be
2980 * a proper error type here.
2981 */
2982 xmlSchemaPErr2(ctxt, node, child,
2983 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2984 "Attribute declaration %s has both (\"ref\" or "
2985 "\"type\") and <simpleType>\n", name, NULL);
2986 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00002987 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002988 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002989 }
2990 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002991 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2992 "attribute %s has unexpected content\n", name,
2993 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002994 }
2995
2996 return (ret);
2997}
2998
2999/**
3000 * xmlSchemaParseAttributeGroup:
3001 * @ctxt: a schema validation context
3002 * @schema: the schema being built
3003 * @node: a subtree containing XML Schema informations
3004 *
3005 * parse a XML schema Attribute Group declaration
3006 * *WARNING* this interface is highly subject to change
3007 *
3008 * Returns the attribute group or NULL in case of error.
3009 */
3010static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003011xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003012 xmlSchemaPtr schema, xmlNodePtr node,
3013 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003014{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003015 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003016 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00003017 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003018 const xmlChar *oldcontainer;
3019 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003020
3021 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3022 return (NULL);
3023 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003024 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003025 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003026 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
3027 if (ref == NULL) {
3028 xmlSchemaPErr2(ctxt, node, child,
3029 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
3030 "AttributeGroup has no name nor ref\n", NULL,
3031 NULL);
3032 return (NULL);
3033 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003034 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
3035 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003036 if (name == NULL) {
3037 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
3038 return (NULL);
3039 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003040 }
3041 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
3042 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003043 return (NULL);
3044 }
3045 ret->ref = ref;
3046 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00003047 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00003048 if (topLevel)
3049 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003050 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00003051 child = node->children;
3052 ctxt->container = name;
3053 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003054 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3055 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003056 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003057 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
3058 /* Seems that this can be removed. */
3059 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00003060 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003061 (IS_SCHEMA(child, "attributeGroup"))) {
3062 attr = NULL;
3063 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003064 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003065 } else if (IS_SCHEMA(child, "attributeGroup")) {
3066 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00003067 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003068 }
3069 if (attr != NULL) {
3070 if (last == NULL) {
3071 ret->attributes = attr;
3072 last = attr;
3073 } else {
3074 last->next = attr;
3075 last = attr;
3076 }
3077 }
3078 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003079 }
3080 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003081 TODO
3082 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003083 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003084 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003085 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003086 xmlSchemaPErr2(ctxt, node, child,
3087 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
3088 "attribute group %s has unexpected content\n", name,
3089 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003090 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003091 ctxt->container = oldcontainer;
3092 return (ret);
3093}
3094
3095/**
3096 * xmlSchemaParseElement:
3097 * @ctxt: a schema validation context
3098 * @schema: the schema being built
3099 * @node: a subtree containing XML Schema informations
3100 *
3101 * parse a XML schema Element declaration
3102 * *WARNING* this interface is highly subject to change
3103 *
William M. Bracke7091952004-05-11 15:09:58 +00003104 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00003105 */
3106static xmlSchemaElementPtr
3107xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003108 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003109{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003110 const xmlChar *name, *fixed;
3111 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003112 xmlSchemaElementPtr ret;
3113 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003114 const xmlChar *oldcontainer;
3115 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00003116 xmlAttrPtr attr;
3117
3118 /* 3.3.3 Constraints on XML Representations of Element Declarations */
3119 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003120
3121 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3122 return (NULL);
3123 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003124 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003125 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003126 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00003127 /* 3.3.3 : 2.1
3128 * One of ref or name must be present, but not both
3129 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003130 if (ref == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00003131 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003132 XML_SCHEMAP_ELEM_NONAME_NOREF,
Daniel Veillard3646d642004-06-02 19:19:14 +00003133 "Element declaration has no name nor ref\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003134 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00003135 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003136
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003137 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
3138 name = (const xmlChar *) buf;
3139 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
3140 } else {
William M. Bracke7091952004-05-11 15:09:58 +00003141 const xmlChar *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003142
William M. Bracke7091952004-05-11 15:09:58 +00003143 /* Evaluate the target namespace */
3144 if (schema->targetNamespace != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003145 if (topLevel) {
William M. Bracke7091952004-05-11 15:09:58 +00003146 ns = schema->targetNamespace;
3147 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
3148 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
3149 BAD_CAST "qualified")) {
3150 ns = schema->targetNamespace;
3151 }
3152 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
3153 ns = schema->targetNamespace;
3154 }
3155 }
3156 /*local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
3157 ret = xmlSchemaAddElement(ctxt, schema, name, ns);
3158 /* 3.3.3 : 2.1
3159 * One of ref or name must be present, but not both
3160 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003161 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00003162 xmlSchemaPErr(ctxt, node,
3163 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
3164 "Element declaration has both, \"name\" and "
3165 "\"ref\"\n", NULL, NULL);
3166 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003167 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003168 if (ret != NULL)
3169 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00003170 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003171 return (NULL);
3172 }
3173 ret->type = XML_SCHEMA_TYPE_ELEMENT;
3174 ret->ref = ref;
3175 ret->refNs = refNs;
3176 if (ref != NULL)
3177 ret->flags |= XML_SCHEMAS_ELEM_REF;
William M. Bracke7091952004-05-11 15:09:58 +00003178
3179 /* 3.3.3 : 2.2 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003180 if ((!topLevel) && (ref != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00003181 attr = node->properties;
3182 while (attr != NULL) {
3183 if ((attr->ns == NULL) &&
3184 (!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
3185 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
3186 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
3187 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
3188
3189 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
3190 "Element declaration %s: only minOccurs, maxOccurs "
3191 "and id are allowed in addition to ref\n",
3192 ret->name, NULL);
3193 }
3194 attr = attr->next;
3195 }
3196 }
3197
Daniel Veillard3646d642004-06-02 19:19:14 +00003198 if (topLevel) {
3199 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Daniel Veillard3646d642004-06-02 19:19:14 +00003201 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003202 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
3203 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
3204 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Daniel Veillard3646d642004-06-02 19:19:14 +00003205 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillard4255d502002-04-16 15:50:10 +00003206 ctxt->container = name;
3207
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003208 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003209 ret->namedType =
William M. Bracke7091952004-05-11 15:09:58 +00003210 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003211 ret->substGroup =
3212 xmlGetQNameProp(ctxt, node, "substitutionGroup",
3213 &(ret->substGroupNs));
Daniel Veillard3646d642004-06-02 19:19:14 +00003214 if ((ret->substGroup != NULL) && (!topLevel)) {
William M. Bracke7091952004-05-11 15:09:58 +00003215 /* 3.3.6 : 3 */
3216 /*
3217 * TODO: This seems to be redundant, since the schema for schemas
3218 * already prohibits the use of the "substitutionGroup" attribute
3219 * in local element declarations.
3220 */
3221 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
3222 "Element declaration %s: substitutionGroup is allowed "
3223 "on top-level declarations only\n", ret->name, NULL);
3224
3225 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003226 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00003227 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
3228 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003229
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003230 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00003231 if ((ret->value != NULL) && (fixed != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00003232 /* 3.3.3 : 1
3233 * default and fixed must not both be present.
3234 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003235 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
3236 "Element %s has both default and fixed\n",
3237 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003238 } else if (fixed != NULL) {
3239 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003240 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00003241 }
3242
3243 child = node->children;
3244 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003245 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3246 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003247 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003248
William M. Bracke7091952004-05-11 15:09:58 +00003249 if (ref != NULL) {
3250 /* 3.3.3 (2.2) */
3251 while (child != NULL) {
3252 if ((IS_SCHEMA(child, "complexType")) ||
3253 (IS_SCHEMA(child, "simpleType")) ||
3254 (IS_SCHEMA(child, "unique")) ||
3255 (IS_SCHEMA(child, "key")) ||
3256 (IS_SCHEMA(child, "keyref"))) {
3257
3258 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_REF_AND_CONTENT,
3259 "Element declaration %s: only annotation is "
3260 "allowed as content in addition to ref\n",
3261 ret->name, NULL);
3262 } else {
3263 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
3264 "element %s has unexpected content\n", name, NULL);
3265 }
3266 child = child->next;
3267 }
3268 } else {
3269 if (IS_SCHEMA(child, "complexType")) {
3270 /* 3.3.3 : 3
3271 * type and either <simpleType> or <complexType> are mutually
3272 * exclusive
3273 */
3274 if (ret->namedType != NULL) {
3275 xmlSchemaPErr2(ctxt, node, child,
3276 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
3277 "Element declaration %s has both \"type\" "
3278 "and a local complex type\n",
3279 ret->name, NULL);
3280 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00003281 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00003282 child = child->next;
3283 } else if (IS_SCHEMA(child, "simpleType")) {
3284 /* 3.3.3 : 3
3285 * type and either <simpleType> or <complexType> are
3286 * mutually exclusive
3287 */
3288 if (ret->namedType != NULL) {
3289 xmlSchemaPErr2(ctxt, node, child,
3290 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
3291 "Element declaration %s has both \"type\" "
3292 "and a local simple type\n",
3293 ret->name, NULL);
3294 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00003295 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00003296 child = child->next;
3297 }
3298
3299 while ((IS_SCHEMA(child, "unique")) ||
3300 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
3301 TODO child = child->next;
3302 }
3303 if (child != NULL) {
3304 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
3305 "element %s has unexpected content\n", name, NULL);
3306 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003307 }
3308
3309 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003310 return (ret);
3311}
3312
3313/**
3314 * xmlSchemaParseUnion:
3315 * @ctxt: a schema validation context
3316 * @schema: the schema being built
3317 * @node: a subtree containing XML Schema informations
3318 *
3319 * parse a XML schema Union definition
3320 * *WARNING* this interface is highly subject to change
3321 *
William M. Bracke7091952004-05-11 15:09:58 +00003322 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003323 * 1 in case of success.
3324 */
3325static xmlSchemaTypePtr
3326xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003327 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003328{
3329 xmlSchemaTypePtr type, subtype, last = NULL;
3330 xmlNodePtr child = NULL;
3331 xmlChar name[30];
3332
3333 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3334 return (NULL);
3335
3336
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003337 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003338 type = xmlSchemaNewUnion(ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003339 if (type == NULL)
3340 return (NULL);
3341 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003342 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003343 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00003344
3345 child = node->children;
3346 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003347 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3348 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003349 }
3350 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003351 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00003352 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003353 if (subtype != NULL) {
3354 if (last == NULL) {
3355 type->subtypes = subtype;
3356 last = subtype;
3357 } else {
3358 last->next = subtype;
3359 last = subtype;
3360 }
3361 last->next = NULL;
3362 }
3363 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003364 }
3365 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003366 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
3367 "Union %s has unexpected content\n", type->name,
3368 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003369 }
3370 return (type);
3371}
3372
3373/**
3374 * xmlSchemaParseList:
3375 * @ctxt: a schema validation context
3376 * @schema: the schema being built
3377 * @node: a subtree containing XML Schema informations
3378 *
3379 * parse a XML schema List definition
3380 * *WARNING* this interface is highly subject to change
3381 *
William M. Bracke7091952004-05-11 15:09:58 +00003382 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003383 * 1 in case of success.
3384 */
3385static xmlSchemaTypePtr
3386xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003387 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003388{
3389 xmlSchemaTypePtr type, subtype;
3390 xmlNodePtr child = NULL;
3391 xmlChar name[30];
Daniel Veillard01fa6152004-06-29 17:04:39 +00003392 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003393
3394 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3395 return (NULL);
3396
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003397 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003398 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003399 if (type == NULL)
3400 return (NULL);
3401 type->node = node;
3402 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003403 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003404
3405 child = node->children;
3406 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003407 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3408 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003409 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003410 /*
3411 * Check type of "itemType".
3412 */
3413 attr = xmlSchemaGetPropNode(node, "itemType");
3414 if (attr != NULL) {
3415 type->base = xmlGetQNameProp(ctxt, node, "itemType", &(type->baseNs));
3416 xmlSchemaParseSchemaAttrValue(ctxt, attr,
3417 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
3418
3419 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003420 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003421 if (IS_SCHEMA(child, "simpleType")) {
3422 subtype = (xmlSchemaTypePtr)
3423 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
3424 type->subtypes = subtype;
3425 /*
3426 * This is a hack to save the information that a local
3427 * simple type was defined.
3428 */
3429 type->baseType = subtype;
3430 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003431 }
3432 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003433 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
3434 "List %s has unexpected content\n", type->name,
3435 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003436 }
3437 return (type);
3438}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003439
Daniel Veillard4255d502002-04-16 15:50:10 +00003440/**
3441 * xmlSchemaParseSimpleType:
3442 * @ctxt: a schema validation context
3443 * @schema: the schema being built
3444 * @node: a subtree containing XML Schema informations
3445 *
3446 * parse a XML schema Simple Type definition
3447 * *WARNING* this interface is highly subject to change
3448 *
William M. Bracke7091952004-05-11 15:09:58 +00003449 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003450 * 1 in case of success.
3451 */
3452static xmlSchemaTypePtr
3453xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003454 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003455{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003456 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00003457 xmlNodePtr child = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003458 const xmlChar *propVal;
Daniel Veillard4255d502002-04-16 15:50:10 +00003459
3460 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3461 return (NULL);
3462
Daniel Veillard01fa6152004-06-29 17:04:39 +00003463 ctxtType = ctxt->ctxtType;
3464 propVal = xmlSchemaGetProp(ctxt, node, "name");
3465 if (propVal == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003466 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003467
William M. Bracke7091952004-05-11 15:09:58 +00003468 snprintf(buf, 99, "simpleType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003469 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00003470 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00003471 if (!topLevel) {
3472 xmlSchemaPErr(ctxt, node,
3473 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3474 "The attribute \"name\" is not allowed on a local "
3475 "simpleType definition\n",
3476 propVal, NULL);
3477 return (NULL);
3478 }
3479 /*
3480 * "name" has to be of type NCName.
3481 * TODO: Actually this should be validated by the schema for schemas.
3482 */
3483 if (xmlSchemaParseSchemaAttrValue(ctxt,
3484 xmlSchemaGetPropNode(node, BAD_CAST "name"),
3485 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME)) != 0)
3486 return (NULL);
3487 type = xmlSchemaAddType(ctxt, schema, propVal, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003488 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003489 if (type == NULL)
3490 return (NULL);
3491 type->node = node;
3492 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillard3646d642004-06-02 19:19:14 +00003493 if (topLevel)
3494 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003495 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003496 propVal = xmlSchemaGetProp(ctxt, node, "final");
3497 if (propVal == NULL) {
3498 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
3499 } else {
3500 if (xmlStrEqual(propVal, BAD_CAST "#all")) {
3501 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
3502 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
3503 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
3504 } else {
3505 const xmlChar *end, *cur = propVal;
3506 xmlChar *item;
3507
3508 do {
3509 while (IS_BLANK_CH(*cur))
3510 cur++;
3511 end = cur;
3512 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
3513 end++;
3514 if (end == cur)
3515 break;
3516 item = xmlStrndup(cur, end - cur);
3517 if (xmlStrEqual(item, BAD_CAST "restriction")) {
3518 if ((type->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) == 0)
3519 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
3520 } else if (xmlStrEqual(item, BAD_CAST "list")) {
3521 if ((type->flags & XML_SCHEMAS_TYPE_FINAL_LIST) == 0)
3522 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
3523 } else if (xmlStrEqual(item, BAD_CAST "union")) {
3524 if ((type->flags & XML_SCHEMAS_TYPE_FINAL_UNION) == 0)
3525 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
3526 } else {
3527 xmlSchemaPErr(ctxt, node,
3528 XML_SCHEMAS_ERR_INTERNAL,
3529 "The attribute \"final\" of type \"%s\" "
3530 "has an invalid value\n",
3531 type->name, NULL);
3532 }
3533 if (item != NULL)
3534 xmlFree(item);
3535 cur = end;
3536 } while (*cur != 0);
3537 }
3538 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003539 child = node->children;
3540 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003541 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3542 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003543 }
3544 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003545 ctxt->ctxtType = type;
3546 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00003547 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003548 subtype = (xmlSchemaTypePtr)
3549 xmlSchemaParseRestriction(ctxt, schema, child, 1);
3550 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003551 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003552 subtype = (xmlSchemaTypePtr)
3553 xmlSchemaParseList(ctxt, schema, child);
3554 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003555 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003556 subtype = (xmlSchemaTypePtr)
3557 xmlSchemaParseUnion(ctxt, schema, child);
3558 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003559 }
3560 type->subtypes = subtype;
3561 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003562 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillard01fa6152004-06-29 17:04:39 +00003563 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
3564 "SimpleType \"%s\" has unexpected content\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003565 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003566 } else {
3567 if (subtype == NULL) {
3568 xmlSchemaPErr2(ctxt, node, child,
3569 XML_SCHEMAP_S4S_ELEM_MISSING,
3570 "SimpleType \"%s\" must have one of <restriction> or "
3571 "<list> or <union> as a child\n",
3572 type->name, NULL);
3573 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003574 }
3575
Daniel Veillard01fa6152004-06-29 17:04:39 +00003576 ctxt->ctxtType = ctxtType;
3577
Daniel Veillard4255d502002-04-16 15:50:10 +00003578 return (type);
3579}
3580
3581
3582/**
3583 * xmlSchemaParseGroup:
3584 * @ctxt: a schema validation context
3585 * @schema: the schema being built
3586 * @node: a subtree containing XML Schema informations
3587 *
3588 * parse a XML schema Group definition
3589 * *WARNING* this interface is highly subject to change
3590 *
William M. Bracke7091952004-05-11 15:09:58 +00003591 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003592 * 1 in case of success.
3593 */
3594static xmlSchemaTypePtr
3595xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003596 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003597{
3598 xmlSchemaTypePtr type, subtype;
3599 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003600 const xmlChar *name;
3601 const xmlChar *ref = NULL, *refNs = NULL;
3602 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003603
3604 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3605 return (NULL);
3606
3607
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003608 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003609 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003610 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
3611 if (ref == NULL) {
3612 xmlSchemaPErr2(ctxt, node, child,
3613 XML_SCHEMAP_GROUP_NONAME_NOREF,
3614 "Group has no name nor ref\n", NULL, NULL);
3615 return (NULL);
3616 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003617 if (refNs == NULL)
3618 refNs = schema->targetNamespace;
3619 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
3620 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003622 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 if (type == NULL)
3624 return (NULL);
3625 type->node = node;
3626 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00003627 if (topLevel)
3628 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003629 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003630 type->ref = ref;
3631 type->refNs = refNs;
3632 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3633 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3634
3635 child = node->children;
3636 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003637 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3638 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003639 }
3640 subtype = NULL;
3641 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003642 subtype = (xmlSchemaTypePtr)
3643 xmlSchemaParseAll(ctxt, schema, child);
3644 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003645 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003646 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3647 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003649 subtype = (xmlSchemaTypePtr)
3650 xmlSchemaParseSequence(ctxt, schema, child);
3651 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003652 }
3653 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003654 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003655 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003656 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
3657 "Group %s has unexpected content\n", type->name,
3658 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003659 }
3660
3661 return (type);
3662}
3663
3664/**
3665 * xmlSchemaParseAll:
3666 * @ctxt: a schema validation context
3667 * @schema: the schema being built
3668 * @node: a subtree containing XML Schema informations
3669 *
3670 * parse a XML schema All definition
3671 * *WARNING* this interface is highly subject to change
3672 *
William M. Bracke7091952004-05-11 15:09:58 +00003673 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003674 * 1 in case of success.
3675 */
3676static xmlSchemaTypePtr
3677xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003678 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003679{
3680 xmlSchemaTypePtr type, subtype, last = NULL;
3681 xmlNodePtr child = NULL;
3682 xmlChar name[30];
3683
3684 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3685 return (NULL);
3686
3687
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003688 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003689 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003690 if (type == NULL)
3691 return (NULL);
3692 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00003693 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003694 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003695 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00003696 if (type->minOccurs > 1)
3697 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
3698 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003699 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00003700 if (type->maxOccurs > 1)
3701 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
3702 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003703
3704 child = node->children;
3705 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003706 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3707 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003708 }
3709 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003710 subtype = (xmlSchemaTypePtr)
3711 xmlSchemaParseElement(ctxt, schema, child, 0);
3712 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00003713 if (subtype->minOccurs > 1)
3714 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
3715 "invalid value for minOccurs (must be 0 or 1)\n",
3716 NULL, NULL);
3717 if (subtype->maxOccurs > 1)
3718 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
3719 "invalid value for maxOccurs (must be 0 or 1)\n",
3720 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003721 if (last == NULL) {
3722 type->subtypes = subtype;
3723 last = subtype;
3724 } else {
3725 last->next = subtype;
3726 last = subtype;
3727 }
3728 last->next = NULL;
3729 }
3730 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003731 }
3732 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003733 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
3734 "All %s has unexpected content\n", type->name,
3735 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003736 }
3737
3738 return (type);
3739}
3740
3741/**
Daniel Veillard1d913862003-11-21 00:28:39 +00003742 * xmlSchemaImportSchema
3743 *
3744 * @ctxt: a schema validation context
3745 * @schemaLocation: an URI defining where to find the imported schema
3746 *
3747 * import a XML schema
3748 * *WARNING* this interface is highly subject to change
3749 *
3750 * Returns -1 in case of error and 1 in case of success.
3751 */
3752static xmlSchemaImportPtr
3753xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
3754 const xmlChar *schemaLocation)
3755{
3756 xmlSchemaImportPtr import;
3757 xmlSchemaParserCtxtPtr newctxt;
3758
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003759 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00003760 if (newctxt == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003761 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00003762 NULL);
3763 return (NULL);
3764 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003765 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
3766 /* Keep the same dictionnary for parsing, really */
3767 xmlDictReference(ctxt->dict);
3768 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003769 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003770 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
3771
Daniel Veillard1d913862003-11-21 00:28:39 +00003772 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
3773 ctxt->userData);
3774
3775 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
3776 if (import == NULL) {
3777 xmlSchemaPErrMemory(NULL, "allocating imported schema",
3778 NULL);
3779 xmlSchemaFreeParserCtxt(newctxt);
3780 return (NULL);
3781 }
3782
3783 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003784 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00003785 import->schema = xmlSchemaParse(newctxt);
3786
3787 if (import->schema == NULL) {
3788 /* FIXME use another error enum here ? */
3789 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
3790 "failed to import schema at location %s\n",
3791 schemaLocation, NULL);
3792
3793 xmlSchemaFreeParserCtxt(newctxt);
Daniel Veillard1d913862003-11-21 00:28:39 +00003794 xmlFree(import);
3795 return NULL;
3796 }
3797
3798 xmlSchemaFreeParserCtxt(newctxt);
3799 return import;
3800}
3801
3802
3803/**
Daniel Veillard5a872412002-05-22 06:40:27 +00003804 * xmlSchemaParseImport:
3805 * @ctxt: a schema validation context
3806 * @schema: the schema being built
3807 * @node: a subtree containing XML Schema informations
3808 *
3809 * parse a XML schema Import definition
3810 * *WARNING* this interface is highly subject to change
3811 *
William M. Bracke7091952004-05-11 15:09:58 +00003812 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard5a872412002-05-22 06:40:27 +00003813 * 1 in case of success.
3814 */
3815static int
3816xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003817 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00003818{
3819 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00003820 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003821 const xmlChar *namespace;
3822 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00003823 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00003824 xmlURIPtr check;
3825
Daniel Veillard1d913862003-11-21 00:28:39 +00003826
Daniel Veillard5a872412002-05-22 06:40:27 +00003827 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3828 return (-1);
3829
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003830 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00003831 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003832 check = xmlParseURI((const char *) namespace);
3833 if (check == NULL) {
3834 xmlSchemaPErr2(ctxt, node, child,
3835 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
3836 "Import namespace attribute is not an URI: %s\n",
3837 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003838 return (-1);
3839 } else {
3840 xmlFreeURI(check);
3841 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003842 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003843 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00003844 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003845 xmlChar *base = NULL;
3846 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003847 check = xmlParseURI((const char *) schemaLocation);
3848 if (check == NULL) {
3849 xmlSchemaPErr2(ctxt, node, child,
3850 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
3851 "Import schemaLocation attribute is not an URI: %s\n",
3852 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003853 return (-1);
3854 } else {
3855 xmlFreeURI(check);
3856 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003857 base = xmlNodeGetBase(node->doc, node);
3858 if (base == NULL) {
3859 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3860 } else {
3861 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003862 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00003863 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003864 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003865 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3866 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00003867 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003868 }
3869 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003870 schema->schemasImports = xmlHashCreate(10);
3871 if (schema->schemasImports == NULL) {
3872 xmlSchemaPErr2(ctxt, node, child,
3873 XML_SCHEMAP_FAILED_BUILD_IMPORT,
3874 "Internal: failed to build import table\n",
3875 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003876 return (-1);
3877 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003878 }
3879 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003880 import = xmlHashLookup(schema->schemasImports,
3881 XML_SCHEMAS_DEFAULT_NAMESPACE);
3882 if (import != NULL)
3883 previous = import->schemaLocation;
3884 else
3885 previous = NULL;
3886
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003887 if (schemaLocation != NULL) {
3888 if (previous != NULL) {
3889 if (!xmlStrEqual(schemaLocation, previous)) {
3890 xmlSchemaPErr2(ctxt, node, child,
3891 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003892 "Redefining import for default namespace "
3893 "with a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003894 schemaLocation, NULL);
3895 }
3896 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003897 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3898 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003899 return (-1);
3900 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003901 xmlHashAddEntry(schema->schemasImports,
3902 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00003903 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003904 }
3905 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003906 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003907 import = xmlHashLookup(schema->schemasImports, namespace);
3908 if (import != NULL)
3909 previous = import->schemaLocation;
3910 else
3911 previous = NULL;
3912
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003913 if (schemaLocation != NULL) {
3914 if (previous != NULL) {
3915 if (!xmlStrEqual(schemaLocation, previous)) {
3916 xmlSchemaPErr2(ctxt, node, child,
3917 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003918 "Redefining import for namespace %s with "
3919 "a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003920 namespace, schemaLocation);
3921 }
3922 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003923 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3924 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003925 return (-1);
3926 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003927 if (!xmlStrEqual(import->schema->targetNamespace, namespace)) {
3928 if (namespace == NULL) {
3929 if (import->schema->targetNamespace != NULL) {
William M. Brack767265d2004-06-03 10:50:29 +00003930 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_2,
Daniel Veillard3646d642004-06-02 19:19:14 +00003931 "There is no namespace attribute on the <import> "
3932 "element information item, so the imported document "
3933 "must have no targetNamespace attribute.\n",
3934 NULL, NULL);
3935 }
3936 } else {
3937 if (import->schema->targetNamespace != NULL) {
William M. Brack767265d2004-06-03 10:50:29 +00003938 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_1,
Daniel Veillard3646d642004-06-02 19:19:14 +00003939 "The namespace attribute \"%s\" of an <import> "
3940 "element information item must be identical to the "
3941 "targetNamespace attribute \"%s\" of the "
3942 "imported document.\n",
3943 namespace, import->schema->targetNamespace);
3944 } else {
William M. Brack767265d2004-06-03 10:50:29 +00003945 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_1,
Daniel Veillard3646d642004-06-02 19:19:14 +00003946 "The namespace attribute on the <import> "
3947 "element information item, requires the imported "
3948 "document to have a targetNamespace attribute "
3949 "with the value \"%s\".\n",
3950 namespace, NULL);
3951 }
3952 }
3953 xmlSchemaFreeImport(import);
3954 return (-1);
3955 }
3956
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003957 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00003958 namespace, import);
Daniel Veillard3646d642004-06-02 19:19:14 +00003959
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003960 }
3961 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003962 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003963
3964 child = node->children;
3965 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003966 /*
3967 * the annotations here are simply discarded ...
3968 */
3969 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00003970 }
3971 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003972 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
3973 "Import has unexpected content\n", NULL, NULL);
3974 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003975 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003976 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003977}
3978
3979/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003980 * xmlSchemaCleanupDoc:
3981 * @ctxt: a schema validation context
3982 * @node: the root of the document.
3983 *
3984 * removes unwanted nodes in a schemas document tree
3985 */
3986static void
3987xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
3988{
3989 xmlNodePtr delete, cur;
3990
3991 if ((ctxt == NULL) || (root == NULL)) return;
3992
3993 /*
3994 * Remove all the blank text nodes
3995 */
3996 delete = NULL;
3997 cur = root;
3998 while (cur != NULL) {
3999 if (delete != NULL) {
4000 xmlUnlinkNode(delete);
4001 xmlFreeNode(delete);
4002 delete = NULL;
4003 }
4004 if (cur->type == XML_TEXT_NODE) {
4005 if (IS_BLANK_NODE(cur)) {
4006 if (xmlNodeGetSpacePreserve(cur) != 1) {
4007 delete = cur;
4008 }
4009 }
4010 } else if ((cur->type != XML_ELEMENT_NODE) &&
4011 (cur->type != XML_CDATA_SECTION_NODE)) {
4012 delete = cur;
4013 goto skip_children;
4014 }
4015
4016 /*
4017 * Skip to next node
4018 */
4019 if (cur->children != NULL) {
4020 if ((cur->children->type != XML_ENTITY_DECL) &&
4021 (cur->children->type != XML_ENTITY_REF_NODE) &&
4022 (cur->children->type != XML_ENTITY_NODE)) {
4023 cur = cur->children;
4024 continue;
4025 }
4026 }
4027 skip_children:
4028 if (cur->next != NULL) {
4029 cur = cur->next;
4030 continue;
4031 }
4032
4033 do {
4034 cur = cur->parent;
4035 if (cur == NULL)
4036 break;
4037 if (cur == root) {
4038 cur = NULL;
4039 break;
4040 }
4041 if (cur->next != NULL) {
4042 cur = cur->next;
4043 break;
4044 }
4045 } while (cur != NULL);
4046 }
4047 if (delete != NULL) {
4048 xmlUnlinkNode(delete);
4049 xmlFreeNode(delete);
4050 delete = NULL;
4051 }
4052}
4053
4054/**
4055 * xmlSchemaParseSchemaTopLevel:
4056 * @ctxt: a schema validation context
4057 * @schema: the schemas
4058 * @nodes: the list of top level nodes
4059 *
4060 * Returns the internal XML Schema structure built from the resource or
4061 * NULL in case of error
4062 */
4063static void
4064xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
4065 xmlSchemaPtr schema, xmlNodePtr nodes)
4066{
4067 xmlNodePtr child;
4068 xmlSchemaAnnotPtr annot;
4069
4070 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
4071 return;
4072
4073 child = nodes;
4074 while ((IS_SCHEMA(child, "include")) ||
4075 (IS_SCHEMA(child, "import")) ||
4076 (IS_SCHEMA(child, "redefine")) ||
4077 (IS_SCHEMA(child, "annotation"))) {
4078 if (IS_SCHEMA(child, "annotation")) {
4079 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4080 if (schema->annot == NULL)
4081 schema->annot = annot;
4082 else
4083 xmlSchemaFreeAnnot(annot);
4084 } else if (IS_SCHEMA(child, "import")) {
4085 xmlSchemaParseImport(ctxt, schema, child);
4086 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004087 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004088 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004089 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004090 } else if (IS_SCHEMA(child, "redefine")) {
4091 TODO
4092 }
4093 child = child->next;
4094 }
4095 while (child != NULL) {
4096 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004097 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004098 child = child->next;
4099 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004100 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004101 child = child->next;
4102 } else if (IS_SCHEMA(child, "element")) {
4103 xmlSchemaParseElement(ctxt, schema, child, 1);
4104 child = child->next;
4105 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004106 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004107 child = child->next;
4108 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004109 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004110 child = child->next;
4111 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004112 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004113 child = child->next;
4114 } else if (IS_SCHEMA(child, "notation")) {
4115 xmlSchemaParseNotation(ctxt, schema, child);
4116 child = child->next;
4117 } else {
4118 xmlSchemaPErr2(ctxt, NULL, child,
4119 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
4120 "Schemas: unexpected element %s here \n",
4121 child->name, NULL);
4122 child = child->next;
4123 }
4124 while (IS_SCHEMA(child, "annotation")) {
4125 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4126 if (schema->annot == NULL)
4127 schema->annot = annot;
4128 else
4129 xmlSchemaFreeAnnot(annot);
4130 child = child->next;
4131 }
4132 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004133 ctxt->parentItem = NULL;
4134 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004135}
4136
4137/**
4138 * xmlSchemaParseInclude:
4139 * @ctxt: a schema validation context
4140 * @schema: the schema being built
4141 * @node: a subtree containing XML Schema informations
4142 *
4143 * parse a XML schema Include definition
4144 *
William M. Bracke7091952004-05-11 15:09:58 +00004145 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004146 * 1 in case of success.
4147 */
4148static int
4149xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4150 xmlNodePtr node)
4151{
4152 xmlNodePtr child = NULL;
4153 const xmlChar *schemaLocation;
4154 xmlURIPtr check;
4155 xmlDocPtr doc;
4156 xmlNodePtr root;
4157 xmlSchemaIncludePtr include;
4158
4159
4160 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4161 return (-1);
4162
4163 /*
4164 * Preliminary step, extract the URI-Reference for the include and
4165 * make an URI from the base.
4166 */
4167 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
4168 if (schemaLocation != NULL) {
4169 xmlChar *base = NULL;
4170 xmlChar *URI = NULL;
4171 check = xmlParseURI((const char *) schemaLocation);
4172 if (check == NULL) {
4173 xmlSchemaPErr2(ctxt, node, child,
4174 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
4175 "Include schemaLocation attribute is not an URI: %s\n",
4176 schemaLocation, NULL);
4177 return (-1);
4178 } else {
4179 xmlFreeURI(check);
4180 }
4181 base = xmlNodeGetBase(node->doc, node);
4182 if (base == NULL) {
4183 URI = xmlBuildURI(schemaLocation, node->doc->URL);
4184 } else {
4185 URI = xmlBuildURI(schemaLocation, base);
4186 xmlFree(base);
4187 }
4188 if (URI != NULL) {
4189 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
4190 xmlFree(URI);
4191 }
4192 } else {
4193 xmlSchemaPErr2(ctxt, node, child,
4194 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
4195 "Include schemaLocation attribute missing\n",
4196 NULL, NULL);
4197 return (-1);
4198 }
4199
4200 child = node->children;
4201 while (IS_SCHEMA(child, "annotation")) {
4202 /*
4203 * the annotations here are simply discarded ...
4204 */
4205 child = child->next;
4206 }
4207 if (child != NULL) {
4208 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
4209 "Include has unexpected content\n", NULL, NULL);
4210 return (-1);
4211 }
4212
4213 /*
4214 * First step is to parse the input document into an DOM/Infoset
4215 */
4216 doc = xmlReadFile((const char *) schemaLocation, NULL,
4217 SCHEMAS_PARSE_OPTIONS);
4218 if (doc == NULL) {
4219 xmlSchemaPErr(ctxt, NULL,
4220 XML_SCHEMAP_FAILED_LOAD,
4221 "xmlSchemaParse: could not load %s\n",
4222 ctxt->URL, NULL);
4223 return(-1);
4224 }
4225
4226 /*
4227 * Then extract the root of the schema
4228 */
4229 root = xmlDocGetRootElement(doc);
4230 if (root == NULL) {
4231 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4232 XML_SCHEMAP_NOROOT,
4233 "schemas %s has no root", schemaLocation, NULL);
4234 xmlFreeDoc(doc);
4235 return (-1);
4236 }
4237
4238 /*
4239 * Remove all the blank text nodes
4240 */
4241 xmlSchemaCleanupDoc(ctxt, root);
4242
4243 /*
4244 * Check the schemas top level element
4245 */
4246 if (!IS_SCHEMA(root, "schema")) {
4247 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4248 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillard01fa6152004-06-29 17:04:39 +00004249 "File %s is not a schema", schemaLocation, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004250 xmlFreeDoc(doc);
4251 return (-1);
4252 }
4253
4254 /*
4255 * register the include
4256 */
4257 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
4258 if (include == NULL) {
4259 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
4260 xmlFreeDoc(doc);
4261 return (-1);
4262 }
4263
4264 memset(include, 0, sizeof(xmlSchemaInclude));
4265 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
4266 include->doc = doc;
4267 include->next = schema->includes;
4268 schema->includes = include;
4269
4270
4271 /*
4272 * parse the declarations in the included file like if they
4273 * were in the original file.
4274 */
4275 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
4276
4277 return (1);
4278}
4279
4280/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004281 * xmlSchemaParseChoice:
4282 * @ctxt: a schema validation context
4283 * @schema: the schema being built
4284 * @node: a subtree containing XML Schema informations
4285 *
4286 * parse a XML schema Choice definition
4287 * *WARNING* this interface is highly subject to change
4288 *
William M. Bracke7091952004-05-11 15:09:58 +00004289 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004290 * 1 in case of success.
4291 */
4292static xmlSchemaTypePtr
4293xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004294 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004295{
4296 xmlSchemaTypePtr type, subtype, last = NULL;
4297 xmlNodePtr child = NULL;
4298 xmlChar name[30];
4299
4300 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4301 return (NULL);
4302
4303
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004304 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004305 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004306 if (type == NULL)
4307 return (NULL);
4308 type->node = node;
4309 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004310 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004311 type->minOccurs = xmlGetMinOccurs(ctxt, node);
4312 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
4313
4314 child = node->children;
4315 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004316 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4317 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004318 }
4319 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004320 (IS_SCHEMA(child, "group")) ||
4321 (IS_SCHEMA(child, "any")) ||
4322 (IS_SCHEMA(child, "choice")) ||
4323 (IS_SCHEMA(child, "sequence"))) {
4324 subtype = NULL;
4325 if (IS_SCHEMA(child, "element")) {
4326 subtype = (xmlSchemaTypePtr)
4327 xmlSchemaParseElement(ctxt, schema, child, 0);
4328 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004329 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004330 } else if (IS_SCHEMA(child, "any")) {
4331 subtype = xmlSchemaParseAny(ctxt, schema, child);
4332 } else if (IS_SCHEMA(child, "sequence")) {
4333 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4334 } else if (IS_SCHEMA(child, "choice")) {
4335 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4336 }
4337 if (subtype != NULL) {
4338 if (last == NULL) {
4339 type->subtypes = subtype;
4340 last = subtype;
4341 } else {
4342 last->next = subtype;
4343 last = subtype;
4344 }
4345 last->next = NULL;
4346 }
4347 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004348 }
4349 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004350 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
4351 "Choice %s has unexpected content\n", type->name,
4352 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004353 }
4354
4355 return (type);
4356}
4357
4358/**
4359 * xmlSchemaParseSequence:
4360 * @ctxt: a schema validation context
4361 * @schema: the schema being built
4362 * @node: a subtree containing XML Schema informations
4363 *
4364 * parse a XML schema Sequence definition
4365 * *WARNING* this interface is highly subject to change
4366 *
William M. Bracke7091952004-05-11 15:09:58 +00004367 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004368 * 1 in case of success.
4369 */
4370static xmlSchemaTypePtr
4371xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004372 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004373{
4374 xmlSchemaTypePtr type, subtype, last = NULL;
4375 xmlNodePtr child = NULL;
4376 xmlChar name[30];
4377
4378 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4379 return (NULL);
4380
4381
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004382 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004383 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004384 if (type == NULL)
4385 return (NULL);
4386 type->node = node;
4387 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004388 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004389 type->minOccurs = xmlGetMinOccurs(ctxt, node);
4390 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
4391
4392 child = node->children;
4393 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004394 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4395 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004396 }
4397 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004398 (IS_SCHEMA(child, "group")) ||
4399 (IS_SCHEMA(child, "any")) ||
4400 (IS_SCHEMA(child, "choice")) ||
4401 (IS_SCHEMA(child, "sequence"))) {
4402 subtype = NULL;
4403 if (IS_SCHEMA(child, "element")) {
4404 subtype = (xmlSchemaTypePtr)
4405 xmlSchemaParseElement(ctxt, schema, child, 0);
4406 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004407 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004408 } else if (IS_SCHEMA(child, "any")) {
4409 subtype = xmlSchemaParseAny(ctxt, schema, child);
4410 } else if (IS_SCHEMA(child, "choice")) {
4411 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4412 } else if (IS_SCHEMA(child, "sequence")) {
4413 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4414 }
4415 if (subtype != NULL) {
4416 if (last == NULL) {
4417 type->subtypes = subtype;
4418 last = subtype;
4419 } else {
4420 last->next = subtype;
4421 last = subtype;
4422 }
4423 last->next = NULL;
4424 }
4425 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004426 }
4427 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004428 xmlSchemaPErr2(ctxt, node, child,
4429 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4430 "Sequence %s has unexpected content\n", type->name,
4431 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004432 }
4433
4434 return (type);
4435}
4436
4437/**
4438 * xmlSchemaParseRestriction:
4439 * @ctxt: a schema validation context
4440 * @schema: the schema being built
4441 * @node: a subtree containing XML Schema informations
4442 * @simple: is that part of a simple type.
4443 *
4444 * parse a XML schema Restriction definition
4445 * *WARNING* this interface is highly subject to change
4446 *
4447 * Returns the type definition or NULL in case of error
4448 */
4449static xmlSchemaTypePtr
4450xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4451 xmlNodePtr node, int simple)
4452{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004453 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004454 xmlNodePtr child = NULL;
4455 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004456 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00004457
4458 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4459 return (NULL);
4460
4461 oldcontainer = ctxt->container;
4462
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004463 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004464 type = xmlSchemaNewRestriction(ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004465 if (type == NULL)
4466 return (NULL);
4467 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004468 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004469 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00004470 if ((type->base == NULL) &&
4471 (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004472 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillard01fa6152004-06-29 17:04:39 +00004473 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
4474 "Restriction \"%s\" must have a \"base\" attribute.\n",
4475 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004476 }
4477 ctxt->container = name;
4478
4479 child = node->children;
4480 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004481 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4482 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004483 }
4484 subtype = NULL;
4485
Daniel Veillard01fa6152004-06-29 17:04:39 +00004486 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
4487 if (IS_SCHEMA(child, "all")) {
4488 subtype = (xmlSchemaTypePtr)
4489 xmlSchemaParseAll(ctxt, schema, child);
4490 child = child->next;
4491 type->subtypes = subtype;
4492 } else if (IS_SCHEMA(child, "choice")) {
4493 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4494 child = child->next;
4495 type->subtypes = subtype;
4496 } else if (IS_SCHEMA(child, "sequence")) {
4497 subtype = (xmlSchemaTypePtr)
4498 xmlSchemaParseSequence(ctxt, schema, child);
4499 child = child->next;
4500 type->subtypes = subtype;
4501 } else if (IS_SCHEMA(child, "group")) {
4502 subtype = (xmlSchemaTypePtr)
4503 xmlSchemaParseGroup(ctxt, schema, child, 0);
4504 child = child->next;
4505 type->subtypes = subtype;
4506 }
4507 } else if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
4508 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
4509 xmlSchemaFacetPtr facet, lastfacet = NULL;
4510
4511 if (IS_SCHEMA(child, "simpleType")) {
4512 subtype = (xmlSchemaTypePtr)
4513 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4514 /*
4515 * For the simple type this serves as the base type.
4516 */
4517 type->baseType = subtype;
4518 /*
4519 * For the complex type this serves as information for the
4520 * definition of the content type.
4521 * Additionally this is a hack for the simple type, to save
4522 * the information that a local simple type was defined; thus
4523 * allowing to check: src-restriction-base-or-simpleType.
4524 */
4525 type->subtypes = subtype;
4526 child = child->next;
4527 }
4528 /*
4529 * Add the facets to the parent simpleType/complexType.
4530 */
4531 while ((IS_SCHEMA(child, "minInclusive")) ||
4532 (IS_SCHEMA(child, "minExclusive")) ||
4533 (IS_SCHEMA(child, "maxInclusive")) ||
4534 (IS_SCHEMA(child, "maxExclusive")) ||
4535 (IS_SCHEMA(child, "totalDigits")) ||
4536 (IS_SCHEMA(child, "fractionDigits")) ||
4537 (IS_SCHEMA(child, "pattern")) ||
4538 (IS_SCHEMA(child, "enumeration")) ||
4539 (IS_SCHEMA(child, "whiteSpace")) ||
4540 (IS_SCHEMA(child, "length")) ||
4541 (IS_SCHEMA(child, "maxLength")) ||
4542 (IS_SCHEMA(child, "minLength"))) {
4543 facet = xmlSchemaParseFacet(ctxt, schema, child);
4544 if (facet != NULL) {
4545 if (lastfacet == NULL)
4546 ctxt->ctxtType->facets = facet;
4547 else
4548 lastfacet->next = facet;
4549 lastfacet = facet;
4550 lastfacet->next = NULL;
4551 }
4552 child = child->next;
4553 }
4554 /*
4555 * Create links for derivation and validation.
4556 */
4557 if (lastfacet != NULL) {
4558 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
4559
4560 facet = ctxt->ctxtType->facets;
4561 do {
4562 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
4563 if (facetLink == NULL) {
4564 xmlSchemaPErrMemory(ctxt, "allocation a facet link", NULL);
4565 xmlFree(facetLink);
4566 return (NULL);
4567 }
4568 facetLink->facet = facet;
4569 facetLink->next = NULL;
4570 if (lastFacetLink == NULL)
4571 ctxt->ctxtType->facetSet = facetLink;
4572 else
4573 lastFacetLink->next = facetLink;
4574 lastFacetLink = facetLink;
4575 facet = facet->next;
4576 } while (facet != NULL);
4577 }
4578 }
4579 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)
4580 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004581 if (child != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00004582 xmlSchemaPErr2(ctxt, node, child,
4583 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
4584 "Restriction \"%s\" has unexpected content.\n",
4585 type->name, NULL);
4586 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004587 ctxt->container = oldcontainer;
4588 return (type);
4589}
4590
4591/**
4592 * xmlSchemaParseExtension:
4593 * @ctxt: a schema validation context
4594 * @schema: the schema being built
4595 * @node: a subtree containing XML Schema informations
4596 *
4597 * parse a XML schema Extension definition
4598 * *WARNING* this interface is highly subject to change
4599 *
4600 * Returns the type definition or NULL in case of error
4601 */
4602static xmlSchemaTypePtr
4603xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004604 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004605{
4606 xmlSchemaTypePtr type, subtype;
4607 xmlNodePtr child = NULL;
4608 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004609 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00004610
4611 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4612 return (NULL);
4613
4614 oldcontainer = ctxt->container;
4615
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004616 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004617 type = xmlSchemaNewExtension(ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004618 if (type == NULL)
4619 return (NULL);
4620 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004621 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004622 ctxt->container = name;
4623
4624 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
4625 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004626 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
4627 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004628 }
4629 child = node->children;
4630 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004631 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4632 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004633 }
4634 subtype = NULL;
4635
4636 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004637 subtype = xmlSchemaParseAll(ctxt, schema, child);
4638 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004639 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004640 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4641 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004642 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004643 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4644 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004645 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004646 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004647 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004648 }
4649 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004650 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004651 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
4652 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004653 xmlSchemaPErr2(ctxt, node, child,
4654 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
4655 "Extension %s has unexpected content\n", type->name,
4656 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004657 }
4658 ctxt->container = oldcontainer;
4659 return (type);
4660}
4661
4662/**
4663 * xmlSchemaParseSimpleContent:
4664 * @ctxt: a schema validation context
4665 * @schema: the schema being built
4666 * @node: a subtree containing XML Schema informations
4667 *
4668 * parse a XML schema SimpleContent definition
4669 * *WARNING* this interface is highly subject to change
4670 *
4671 * Returns the type definition or NULL in case of error
4672 */
4673static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004674xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
4675 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004676{
4677 xmlSchemaTypePtr type, subtype;
4678 xmlNodePtr child = NULL;
4679 xmlChar name[30];
4680
4681 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4682 return (NULL);
4683
William M. Bracke7091952004-05-11 15:09:58 +00004684 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004685 type = xmlSchemaNewSimpleContent(ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004686 if (type == NULL)
4687 return (NULL);
4688 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004689 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004690
4691 child = node->children;
4692 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004693 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4694 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004695 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004696 ctxt->parentItem = type;
4697 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004698 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004699 subtype = (xmlSchemaTypePtr)
4700 xmlSchemaParseRestriction(ctxt, schema, child, 0);
4701 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004702 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004703 subtype = (xmlSchemaTypePtr)
4704 xmlSchemaParseExtension(ctxt, schema, child);
4705 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004706 }
4707 type->subtypes = subtype;
4708 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004709 xmlSchemaPErr2(ctxt, node, child,
4710 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
4711 "SimpleContent %s has unexpected content\n",
4712 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004713 }
4714 return (type);
4715}
4716
4717/**
4718 * xmlSchemaParseComplexContent:
4719 * @ctxt: a schema validation context
4720 * @schema: the schema being built
4721 * @node: a subtree containing XML Schema informations
4722 *
4723 * parse a XML schema ComplexContent definition
4724 * *WARNING* this interface is highly subject to change
4725 *
4726 * Returns the type definition or NULL in case of error
4727 */
4728static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004729xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
4730 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004731{
4732 xmlSchemaTypePtr type, subtype;
4733 xmlNodePtr child = NULL;
4734 xmlChar name[30];
4735
4736 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4737 return (NULL);
4738
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004739 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004740 type = xmlSchemaNewComplexContent(ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004741 if (type == NULL)
4742 return (NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004743 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004744 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004745
4746 child = node->children;
4747 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004748 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4749 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004750 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004751 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004752 subtype = NULL;
4753 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004754 subtype = (xmlSchemaTypePtr)
4755 xmlSchemaParseRestriction(ctxt, schema, child, 0);
4756 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004757 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004758 subtype = (xmlSchemaTypePtr)
4759 xmlSchemaParseExtension(ctxt, schema, child);
4760 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004761 }
4762 type->subtypes = subtype;
4763 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004764 xmlSchemaPErr2(ctxt, node, child,
4765 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
4766 "ComplexContent %s has unexpected content\n",
4767 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004768 }
4769 return (type);
4770}
4771
4772/**
4773 * xmlSchemaParseComplexType:
4774 * @ctxt: a schema validation context
4775 * @schema: the schema being built
4776 * @node: a subtree containing XML Schema informations
4777 *
4778 * parse a XML schema Complex Type definition
4779 * *WARNING* this interface is highly subject to change
4780 *
4781 * Returns the type definition or NULL in case of error
4782 */
4783static xmlSchemaTypePtr
4784xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004785 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004786{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004787 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004788 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004789 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00004790 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004791 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00004792
4793 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4794 return (NULL);
4795
Daniel Veillard01fa6152004-06-29 17:04:39 +00004796 ctxtType = ctxt->ctxtType;
4797
Daniel Veillard4255d502002-04-16 15:50:10 +00004798 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004799 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004800 if (name == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00004801 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004802 name = (const xmlChar *)buf;
4803 type = xmlSchemaAddType(ctxt, schema, name, NULL);
4804 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004805
William M. Bracke7091952004-05-11 15:09:58 +00004806 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
4807 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004808 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004809 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004810 return (NULL);
4811 }
William M. Bracke7091952004-05-11 15:09:58 +00004812 if (xmlGetBooleanProp(ctxt, node, "mixed", 0))
4813 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004814
Daniel Veillard4255d502002-04-16 15:50:10 +00004815 type->node = node;
4816 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillard3646d642004-06-02 19:19:14 +00004817 if (topLevel)
4818 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004819 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004820 ctxt->container = name;
4821
4822 child = node->children;
4823 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004824 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4825 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004826 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004827 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004828 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00004829 /* 3.4.3 : 2.2
4830 * Specifying mixed='true' when the <simpleContent>
4831 * alternative is chosen has no effect
4832 */
4833 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
4834 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004835 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
4836 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004837 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004838 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
4839 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004840 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004841 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004842
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004843 if (IS_SCHEMA(child, "all")) {
4844 subtype = xmlSchemaParseAll(ctxt, schema, child);
4845 child = child->next;
4846 } else if (IS_SCHEMA(child, "choice")) {
4847 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4848 child = child->next;
4849 } else if (IS_SCHEMA(child, "sequence")) {
4850 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4851 child = child->next;
4852 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004853 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004854 child = child->next;
4855 }
4856 if (subtype != NULL)
4857 type->subtypes = subtype;
4858 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004859 }
4860 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004861 xmlSchemaPErr2(ctxt, node, child,
4862 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
4863 "ComplexType %s has unexpected content\n",
4864 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004865 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004866 if (type->attributeWildcard != NULL)
4867 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillard4255d502002-04-16 15:50:10 +00004868 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004869 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004870 return (type);
4871}
4872
Daniel Veillard4255d502002-04-16 15:50:10 +00004873/**
4874 * xmlSchemaParseSchema:
4875 * @ctxt: a schema validation context
4876 * @node: a subtree containing XML Schema informations
4877 *
4878 * parse a XML schema definition from a node set
4879 * *WARNING* this interface is highly subject to change
4880 *
4881 * Returns the internal XML Schema structure built from the resource or
4882 * NULL in case of error
4883 */
4884static xmlSchemaPtr
4885xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4886{
4887 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004888 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004889 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004890 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004891
4892 if ((ctxt == NULL) || (node == NULL))
4893 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004894
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004895 nberrors = ctxt->nberrors;
4896 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004897 if (IS_SCHEMA(node, "schema")) {
4898 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004899 if (schema == NULL)
4900 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004901 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
4902 if (val != NULL) {
4903 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
4904 } else {
4905 schema->targetNamespace = NULL;
4906 }
4907 schema->id = xmlSchemaGetProp(ctxt, node, "id");
4908 schema->version = xmlSchemaGetProp(ctxt, node, "version");
4909 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004910 if (val != NULL) {
4911 if (xmlStrEqual(val, BAD_CAST "qualified"))
4912 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
4913 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4914 xmlSchemaPErr2(ctxt, node, child,
4915 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
4916 "Invalid value %s for elementFormDefault\n",
4917 val, NULL);
4918 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004919 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00004920 /* Removed, since the default value for elementFormDefault
4921 * is "unqualified".
4922 */
4923 /* schema->flags |= XML_SCHEMAS_QUALIF_ELEM; */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004924 }
4925 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004926 if (val != NULL) {
4927 if (xmlStrEqual(val, BAD_CAST "qualified"))
4928 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
4929 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4930 xmlSchemaPErr2(ctxt, node, child,
4931 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
4932 "Invalid value %s for attributeFormDefault\n",
4933 val, NULL);
4934 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004935 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004936
Daniel Veillard01fa6152004-06-29 17:04:39 +00004937 val = xmlSchemaGetProp(ctxt, node, "finalDefault");
4938 if (val != NULL) {
4939 if (xmlStrEqual(val, BAD_CAST "#all")) {
4940 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
4941 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
4942 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_LIST;
4943 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_UNION;
4944 } else {
4945 const xmlChar *end, *cur = val;
4946 xmlChar *item;
4947
4948 do {
4949 while (IS_BLANK_CH(*cur))
4950 cur++;
4951 end = cur;
4952 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4953 end++;
4954 if (end == cur)
4955 break;
4956 item = xmlStrndup(cur, end - cur);
4957 if (xmlStrEqual(item, BAD_CAST "extension")) {
4958 if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) == 0)
4959 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
4960 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
4961 if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) == 0)
4962 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
4963 } else if (xmlStrEqual(item, BAD_CAST "list")) {
4964 if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST) == 0)
4965 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_LIST;
4966 } else if (xmlStrEqual(item, BAD_CAST "union")) {
4967 if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION) == 0)
4968 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_UNION;
4969 } else {
4970 xmlSchemaPErr(ctxt, node,
4971 XML_SCHEMAS_ERR_INTERNAL,
4972 "Invalid value for the attribute \"finalDefault\".\n",
4973 NULL, NULL);
4974 }
4975 if (item != NULL)
4976 xmlFree(item);
4977 cur = end;
4978 } while (*cur != 0);
4979 }
4980 }
4981
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004982 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
4983 } else {
4984 xmlDocPtr doc;
4985
4986 doc = node->doc;
4987
4988 if ((doc != NULL) && (doc->URL != NULL)) {
4989 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4990 XML_SCHEMAP_NOT_SCHEMA,
4991 "File %s is not a schemas", doc->URL, NULL);
4992 } else {
4993 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4994 XML_SCHEMAP_NOT_SCHEMA,
4995 "File is not a schemas", NULL, NULL);
4996 }
4997 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004998 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004999 if (ctxt->nberrors != 0) {
5000 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005001 xmlSchemaFree(schema);
5002 schema = NULL;
5003 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005004 }
5005 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00005006#ifdef DEBUG
5007 if (schema == NULL)
5008 xmlGenericError(xmlGenericErrorContext,
5009 "xmlSchemaParse() failed\n");
5010#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00005011 return (schema);
5012}
5013
5014/************************************************************************
5015 * *
5016 * Validating using Schemas *
5017 * *
5018 ************************************************************************/
5019
5020/************************************************************************
5021 * *
5022 * Reading/Writing Schemas *
5023 * *
5024 ************************************************************************/
5025
5026/**
5027 * xmlSchemaNewParserCtxt:
5028 * @URL: the location of the schema
5029 *
5030 * Create an XML Schemas parse context for that file/resource expected
5031 * to contain an XML Schemas file.
5032 *
5033 * Returns the parser context or NULL in case of error
5034 */
5035xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005036xmlSchemaNewParserCtxt(const char *URL)
5037{
Daniel Veillard4255d502002-04-16 15:50:10 +00005038 xmlSchemaParserCtxtPtr ret;
5039
5040 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005041 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005042
5043 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
5044 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005045 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
5046 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005047 return (NULL);
5048 }
5049 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005050 ret->dict = xmlDictCreate();
5051 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00005052 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005053 return (ret);
5054}
5055
5056/**
Daniel Veillard6045c902002-10-09 21:13:59 +00005057 * xmlSchemaNewMemParserCtxt:
5058 * @buffer: a pointer to a char array containing the schemas
5059 * @size: the size of the array
5060 *
5061 * Create an XML Schemas parse context for that memory buffer expected
5062 * to contain an XML Schemas file.
5063 *
5064 * Returns the parser context or NULL in case of error
5065 */
5066xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005067xmlSchemaNewMemParserCtxt(const char *buffer, int size)
5068{
Daniel Veillard6045c902002-10-09 21:13:59 +00005069 xmlSchemaParserCtxtPtr ret;
5070
5071 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005072 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00005073
5074 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
5075 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005076 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
5077 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00005078 return (NULL);
5079 }
5080 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
5081 ret->buffer = buffer;
5082 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00005083 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00005084 return (ret);
5085}
5086
5087/**
Daniel Veillard9d751502003-10-29 13:21:47 +00005088 * xmlSchemaNewDocParserCtxt:
5089 * @doc: a preparsed document tree
5090 *
5091 * Create an XML Schemas parse context for that document.
5092 * NB. The document may be modified during the parsing process.
5093 *
5094 * Returns the parser context or NULL in case of error
5095 */
5096xmlSchemaParserCtxtPtr
5097xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
5098{
5099 xmlSchemaParserCtxtPtr ret;
5100
5101 if (doc == NULL)
5102 return (NULL);
5103
5104 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
5105 if (ret == NULL) {
5106 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
5107 NULL);
5108 return (NULL);
5109 }
5110 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
5111 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00005112 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00005113 /* The application has responsibility for the document */
5114 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00005115
5116 return (ret);
5117}
5118
5119/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005120 * xmlSchemaFreeParserCtxt:
5121 * @ctxt: the schema parser context
5122 *
5123 * Free the resources associated to the schema parser context
5124 */
5125void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005126xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
5127{
Daniel Veillard4255d502002-04-16 15:50:10 +00005128 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005129 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005130 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005131 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005132 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00005133 xmlFree(ctxt);
5134}
5135
5136/************************************************************************
5137 * *
5138 * Building the content models *
5139 * *
5140 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005141
Daniel Veillard4255d502002-04-16 15:50:10 +00005142/**
5143 * xmlSchemaBuildAContentModel:
5144 * @type: the schema type definition
5145 * @ctxt: the schema parser context
5146 * @name: the element name whose content is being built
5147 *
5148 * Generate the automata sequence needed for that type
5149 */
5150static void
5151xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005152 xmlSchemaParserCtxtPtr ctxt,
5153 const xmlChar * name)
5154{
Daniel Veillard4255d502002-04-16 15:50:10 +00005155 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005156 xmlGenericError(xmlGenericErrorContext,
5157 "Found unexpected type = NULL in %s content model\n",
5158 name);
5159 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005160 }
5161 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005162 case XML_SCHEMA_TYPE_ANY:
5163 /* TODO : handle the namespace too */
5164 /* TODO : make that a specific transition type */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005165 /* Daniel says: use xmlAutomataNewTransition2 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005166 TODO ctxt->state =
5167 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
5168 BAD_CAST "*", NULL);
5169 break;
5170 case XML_SCHEMA_TYPE_ELEMENT:{
5171 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00005172
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005173 /* TODO : handle the namespace too */
5174 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00005175
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005176 if (elem->maxOccurs >= UNBOUNDED) {
5177 if (elem->minOccurs > 1) {
5178 xmlAutomataStatePtr tmp;
5179 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00005180
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005181 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
5182 oldstate,
5183 NULL);
5184 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00005185
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005186 counter = xmlAutomataNewCounter(ctxt->am,
5187 elem->minOccurs -
5188 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00005189
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005190 if (elem->refDecl != NULL) {
5191 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
5192 elem->refDecl,
5193 ctxt,
5194 elem->refDecl->
5195 name);
5196 } else {
5197 ctxt->state =
5198 xmlAutomataNewTransition(ctxt->am,
5199 ctxt->state, NULL,
5200 elem->name, type);
5201 }
5202 tmp = ctxt->state;
5203 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
5204 counter);
5205 ctxt->state =
5206 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
5207 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00005208
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005209 } else {
5210 if (elem->refDecl != NULL) {
5211 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
5212 elem->refDecl,
5213 ctxt,
5214 elem->refDecl->
5215 name);
5216 } else {
5217 ctxt->state =
5218 xmlAutomataNewTransition(ctxt->am,
5219 ctxt->state, NULL,
5220 elem->name, type);
5221 }
5222 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
5223 oldstate);
5224 if (elem->minOccurs == 0) {
5225 /* basically an elem* */
5226 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5227 ctxt->state);
5228 }
5229 }
5230 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
5231 xmlAutomataStatePtr tmp;
5232 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00005233
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005234 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
5235 oldstate, NULL);
5236 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00005237
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005238 counter = xmlAutomataNewCounter(ctxt->am,
5239 elem->minOccurs - 1,
5240 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005241
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005242 if (elem->refDecl != NULL) {
5243 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
5244 elem->refDecl, ctxt,
5245 elem->refDecl->name);
5246 } else {
5247 ctxt->state = xmlAutomataNewTransition(ctxt->am,
5248 ctxt->state,
5249 NULL,
5250 elem->name,
5251 type);
5252 }
5253 tmp = ctxt->state;
5254 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
5255 counter);
5256 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
5257 NULL,
5258 counter);
5259 if (elem->minOccurs == 0) {
5260 /* basically an elem? */
5261 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5262 ctxt->state);
5263 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00005264
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005265 } else {
5266 if (elem->refDecl != NULL) {
5267 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
5268 elem->refDecl, ctxt,
5269 elem->refDecl->name);
5270 } else {
5271 ctxt->state = xmlAutomataNewTransition(ctxt->am,
5272 ctxt->state,
5273 NULL,
5274 elem->name,
5275 type);
5276 }
5277 if (elem->minOccurs == 0) {
5278 /* basically an elem? */
5279 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5280 ctxt->state);
5281 }
5282 }
5283 break;
5284 }
5285 case XML_SCHEMA_TYPE_SEQUENCE:{
5286 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005287
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005288 /*
5289 * If max and min occurances are default (1) then
5290 * simply iterate over the subtypes
5291 */
5292 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
5293 subtypes = type->subtypes;
5294 while (subtypes != NULL) {
5295 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
5296 subtypes = subtypes->next;
5297 }
5298 } else {
5299 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005300
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005301 if (type->maxOccurs >= UNBOUNDED) {
5302 if (type->minOccurs > 1) {
5303 xmlAutomataStatePtr tmp;
5304 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005305
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005306 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
5307 oldstate,
5308 NULL);
5309 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005310
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005311 counter = xmlAutomataNewCounter(ctxt->am,
5312 type->
5313 minOccurs - 1,
5314 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00005315
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005316 subtypes = type->subtypes;
5317 while (subtypes != NULL) {
5318 xmlSchemaBuildAContentModel(subtypes, ctxt,
5319 name);
5320 subtypes = subtypes->next;
5321 }
5322 tmp = ctxt->state;
5323 xmlAutomataNewCountedTrans(ctxt->am, tmp,
5324 oldstate, counter);
5325 ctxt->state =
5326 xmlAutomataNewCounterTrans(ctxt->am, tmp,
5327 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00005328
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005329 } else {
5330 subtypes = type->subtypes;
5331 while (subtypes != NULL) {
5332 xmlSchemaBuildAContentModel(subtypes, ctxt,
5333 name);
5334 subtypes = subtypes->next;
5335 }
5336 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
5337 oldstate);
5338 if (type->minOccurs == 0) {
5339 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5340 ctxt->state);
5341 }
5342 }
5343 } else if ((type->maxOccurs > 1)
5344 || (type->minOccurs > 1)) {
5345 xmlAutomataStatePtr tmp;
5346 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005347
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005348 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
5349 oldstate,
5350 NULL);
5351 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00005352
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005353 counter = xmlAutomataNewCounter(ctxt->am,
5354 type->minOccurs -
5355 1,
5356 type->maxOccurs -
5357 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005358
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005359 subtypes = type->subtypes;
5360 while (subtypes != NULL) {
5361 xmlSchemaBuildAContentModel(subtypes, ctxt,
5362 name);
5363 subtypes = subtypes->next;
5364 }
5365 tmp = ctxt->state;
5366 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
5367 counter);
5368 ctxt->state =
5369 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
5370 counter);
5371 if (type->minOccurs == 0) {
5372 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5373 ctxt->state);
5374 }
Daniel Veillardb509f152002-04-17 16:28:10 +00005375
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005376 } else {
5377 subtypes = type->subtypes;
5378 while (subtypes != NULL) {
5379 xmlSchemaBuildAContentModel(subtypes, ctxt,
5380 name);
5381 subtypes = subtypes->next;
5382 }
5383 if (type->minOccurs == 0) {
5384 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5385 ctxt->state);
5386 }
5387 }
5388 }
5389 break;
5390 }
5391 case XML_SCHEMA_TYPE_CHOICE:{
5392 xmlSchemaTypePtr subtypes;
5393 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00005394
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005395 start = ctxt->state;
5396 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00005397
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005398 /*
5399 * iterate over the subtypes and remerge the end with an
5400 * epsilon transition
5401 */
5402 if (type->maxOccurs == 1) {
5403 subtypes = type->subtypes;
5404 while (subtypes != NULL) {
5405 ctxt->state = start;
5406 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
5407 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
5408 subtypes = subtypes->next;
5409 }
5410 } else {
5411 int counter;
5412 xmlAutomataStatePtr hop;
5413 int maxOccurs = type->maxOccurs == UNBOUNDED ?
5414 UNBOUNDED : type->maxOccurs - 1;
5415 int minOccurs =
5416 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00005417
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005418 /*
5419 * use a counter to keep track of the number of transtions
5420 * which went through the choice.
5421 */
5422 counter =
5423 xmlAutomataNewCounter(ctxt->am, minOccurs,
5424 maxOccurs);
5425 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00005426
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005427 subtypes = type->subtypes;
5428 while (subtypes != NULL) {
5429 ctxt->state = start;
5430 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
5431 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
5432 subtypes = subtypes->next;
5433 }
5434 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
5435 counter);
5436 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
5437 counter);
5438 }
5439 if (type->minOccurs == 0) {
5440 xmlAutomataNewEpsilon(ctxt->am, start, end);
5441 }
5442 ctxt->state = end;
5443 break;
5444 }
5445 case XML_SCHEMA_TYPE_ALL:{
5446 xmlAutomataStatePtr start;
5447 xmlSchemaTypePtr subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +00005448 /*
5449 * Changed, since type in not an xmlSchemaElement here.
5450 */
5451 /* xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type; */
5452 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005453 int lax;
5454
5455 subtypes = type->subtypes;
5456 if (subtypes == NULL)
5457 break;
5458 start = ctxt->state;
5459 while (subtypes != NULL) {
5460 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00005461 /*
5462 * the following 'if' was needed to fix bug 139897
5463 * not quite sure why it only needs to be done for
5464 * elements with a 'ref', but it seems to work ok.
5465 */
5466 if (subtypes->ref != NULL)
5467 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
William M. Bracke7091952004-05-11 15:09:58 +00005468 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005469 /* TODO : handle the namespace too */
5470 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
5471 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
5472 ctxt->state, elem->name, 1,
5473 1, subtypes);
5474 } else {
5475 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
5476 ctxt->state, elem->name,
5477 elem->minOccurs,
5478 elem->maxOccurs,
5479 subtypes);
5480 }
5481 subtypes = subtypes->next;
5482 }
5483 lax = type->minOccurs == 0;
5484 ctxt->state =
5485 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
5486 lax);
5487 break;
5488 }
5489 case XML_SCHEMA_TYPE_RESTRICTION:
5490 if (type->subtypes != NULL)
5491 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
5492 break;
5493 case XML_SCHEMA_TYPE_EXTENSION:
5494 if (type->baseType != NULL) {
5495 xmlSchemaTypePtr subtypes;
5496
Daniel Veillardf7627552004-04-22 07:15:40 +00005497 if (type->recurse) {
5498 xmlSchemaPErr(ctxt, type->node,
5499 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
5500 "Schemas: extension type %s is recursive\n",
5501 type->name, NULL);
5502 return;
5503 }
5504 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005505 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00005506 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005507 subtypes = type->subtypes;
5508 while (subtypes != NULL) {
5509 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
5510 subtypes = subtypes->next;
5511 }
5512 } else if (type->subtypes != NULL)
5513 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
5514 break;
5515 case XML_SCHEMA_TYPE_GROUP:
5516 if (type->subtypes == NULL) {
William M. Brack29aa7722004-05-12 00:27:56 +00005517 xmlSchemaTypePtr rgroup;
5518 if (type->ref != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005519 rgroup = xmlSchemaGetGroup(ctxt->schema, type->ref,
William M. Brack29aa7722004-05-12 00:27:56 +00005520 type->refNs);
5521 if (rgroup == NULL) {
5522 xmlSchemaPErr(ctxt, type->node,
5523 XML_SCHEMAP_UNKNOWN_REF,
5524 "Schemas: group %s reference %s is not found",
5525 name, type->ref);
5526 return;
5527 }
5528 xmlSchemaBuildAContentModel(rgroup, ctxt, name);
5529 break;
5530 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005531 }
5532 case XML_SCHEMA_TYPE_COMPLEX:
5533 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5534 if (type->subtypes != NULL)
5535 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
5536 break;
5537 default:
5538 xmlGenericError(xmlGenericErrorContext,
5539 "Found unexpected type %d in %s content model\n",
5540 type->type, name);
5541 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005542 }
5543}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005544
Daniel Veillard4255d502002-04-16 15:50:10 +00005545/**
5546 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005547 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00005548 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005549 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00005550 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005551 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00005552 */
5553static void
5554xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005555 xmlSchemaParserCtxtPtr ctxt,
5556 const xmlChar * name)
5557{
Daniel Veillard4255d502002-04-16 15:50:10 +00005558 xmlAutomataStatePtr start;
5559
Daniel Veillard4255d502002-04-16 15:50:10 +00005560 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005561 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00005562 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005563 elem->contentType = XML_SCHEMA_CONTENT_ANY;
5564 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00005565 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005566 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005567 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005568 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
5569 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005570 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005571
5572#ifdef DEBUG_CONTENT
5573 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005574 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005575#endif
5576
Daniel Veillard4255d502002-04-16 15:50:10 +00005577 ctxt->am = xmlNewAutomata();
5578 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005579 xmlGenericError(xmlGenericErrorContext,
5580 "Cannot create automata for elem %s\n", name);
5581 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005582 }
5583 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
5584 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
5585 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00005586 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005587 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005588 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
5589 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005590 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005591 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
5592 "Content model of %s is not determinist:\n", name,
5593 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00005594 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00005595#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005596 xmlGenericError(xmlGenericErrorContext,
5597 "Content model of %s:\n", name);
5598 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005599#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00005600 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005601 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005602 xmlFreeAutomata(ctxt->am);
5603 ctxt->am = NULL;
5604}
5605
5606/**
5607 * xmlSchemaRefFixupCallback:
5608 * @elem: the schema element context
5609 * @ctxt: the schema parser context
5610 *
5611 * Free the resources associated to the schema parser context
5612 */
5613static void
5614xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005615 xmlSchemaParserCtxtPtr ctxt,
5616 const xmlChar * name,
5617 const xmlChar * context ATTRIBUTE_UNUSED,
5618 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005619{
5620 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005621 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00005622
Daniel Veillard4255d502002-04-16 15:50:10 +00005623 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005624 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005625
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005626 if (elem->subtypes != NULL) {
5627 xmlSchemaPErr(ctxt, elem->node,
5628 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
Daniel Veillard3646d642004-06-02 19:19:14 +00005629 "Schemas: element %s has both ref and subtype\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005630 name, NULL);
5631 return;
5632 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005633 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005634
5635 if (elemDecl == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005636 xmlSchemaPErr(ctxt, elem->node,
5637 XML_SCHEMAP_SRC_RESOLVE,
5638 "Element \"%s\": the QName \"%s\" of the attribute "
5639 "\"ref\" does not resolve to a schema "
5640 "component.\n",
5641 name, elem->ref);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005642 return;
5643 }
5644 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005645 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005646 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005647
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005648 if (elem->subtypes != NULL) {
5649 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
Daniel Veillard3646d642004-06-02 19:19:14 +00005650 "Schemas: element %s has both type and subtype\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005651 name, NULL);
5652 return;
5653 }
5654 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
5655 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00005656
5657 if (typeDecl == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005658 xmlSchemaPErr(ctxt, elem->node,
5659 XML_SCHEMAP_SRC_RESOLVE,
5660 "Element \"%s\": the QName \"%s\" of the attribute "
5661 "\"type\" does not resolve to a schema "
5662 "component.\n", name, elem->namedType);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005663 return;
5664 }
5665 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005666 }
5667}
5668
William M. Bracke7091952004-05-11 15:09:58 +00005669/**
5670 * xmlSchemaParseListRefFixup:
5671 * @type: the schema type definition
5672 * @ctxt: the schema parser context
5673 *
5674 * Fixup of the itemType reference of the list type.
5675 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00005676static void
William M. Bracke7091952004-05-11 15:09:58 +00005677xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005678{
5679 /*
5680 * src-list-itemType-or-simpleType
5681 * Either the itemType [attribute] or the <simpleType> [child] of
5682 * the <list> element must be present, but not both.
5683 */
5684 if (((type->base == NULL) &&
5685 (type->subtypes == NULL)) ||
5686 ((type->base != NULL) &&
5687 (type->subtypes != NULL))) {
5688 /*
5689 * src-restriction-base-or-simpleType
5690 * Either the base [attribute] or the simpleType [child] of the
5691 * <restriction> element must be present, but not both.
5692 */
5693 xmlSchemaPErr(ctxt, type->node,
5694 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
5695 "List \"%s\": "
5696 "Either the \"base\" attribute or the <simpleType> child "
5697 "must be present, but not both.\n",
5698 type->name, NULL);
5699 } else if (type->base!= NULL) {
5700 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
5701 if (type->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005702 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_TYPE,
Daniel Veillard01fa6152004-06-29 17:04:39 +00005703 "List \"%s\" references an unknown item type: \"%s\"\n",
5704 type->name, type->base);
5705 }
5706 }
5707 if ((type->subtypes != NULL) &&
5708 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
5709 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005710}
5711
5712/**
5713 * xmlSchemaParseUnionRefCheck:
5714 * @typeDecl: the schema type definition
5715 * @ctxt: the schema parser context
5716 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005717 * Checks and builds the memberTypes of the union type.
5718 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00005719 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005720static int
William M. Bracke7091952004-05-11 15:09:58 +00005721xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00005722 xmlSchemaParserCtxtPtr ctxt)
5723{
5724 const xmlChar *cur, *end, *prefix, *ncName, *namespace;
5725 xmlChar *tmp;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005726 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
5727 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005728 xmlNsPtr ns;
5729 int len;
5730
Daniel Veillard01fa6152004-06-29 17:04:39 +00005731 /* 1 If the <union> alternative is chosen, then [Definition:]
5732 * define the explicit members as the type definitions ·resolved·
5733 * to by the items in the ·actual value· of the memberTypes [attribute],
5734 * if any, followed by the type definitions corresponding to the
5735 * <simpleType>s among the [children] of <union>, if any.
5736 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00005737
Daniel Veillard01fa6152004-06-29 17:04:39 +00005738 if (type->type != XML_SCHEMA_TYPE_UNION)
5739 return (-1);
5740 if (ctxt->ctxtType == NULL) {
5741 xmlSchemaPErr(ctxt, type->node,
5742 XML_SCHEMAS_ERR_INTERNAL,
5743 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
5744 "available", NULL, NULL);
5745 return (-1);
5746 }
5747 /*
5748 * src-union-memberTypes-or-simpleTypes
5749 * Either the memberTypes [attribute] of the <union> element must
5750 * be non-empty or there must be at least one simpleType [child].
5751 */
5752 if ((type->base == NULL) &&
5753 (type->subtypes == NULL)) {
5754 /*
5755 * src-restriction-base-or-simpleType
5756 * Either the base [attribute] or the simpleType [child] of the
5757 * <restriction> element must be present, but not both.
5758 */
5759 xmlSchemaPErr(ctxt, type->node,
5760 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
5761 "Union \"%s\": "
5762 "Either the \"memberTypes\" attribute must be non-empty "
5763 "or there must be at least one <simpleType> child.\n",
5764 type->name, NULL);
5765 }
5766
5767 ctxtType = ctxt->ctxtType;
5768 if (type->base != NULL) {
5769 cur = type->base;
5770 do {
5771 while (IS_BLANK_CH(*cur))
5772 cur++;
5773 end = cur;
5774 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5775 end++;
5776 if (end == cur)
5777 break;
5778 tmp = xmlStrndup(cur, end - cur);
5779 ncName = xmlSplitQName3(tmp, &len);
5780 if (ncName != NULL) {
5781 prefix = xmlDictLookup(ctxt->dict, tmp, len);
5782 } else {
5783 prefix = NULL;
5784 ncName = tmp;
5785 }
5786 ns = xmlSearchNs(type->node->doc, type->node, prefix);
5787 if (ns == NULL) {
5788 if (prefix != NULL) {
5789 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_PREFIX_UNDEFINED,
5790 "Union \"%s\": the namespace prefix of member type "
5791 "\"%s\" is undefined\n",
5792 type->name, (const xmlChar *) tmp);
5793 }
5794 namespace = NULL;
5795 } else {
5796 namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
5797 }
5798 memberType = xmlSchemaGetType(ctxt->schema, ncName, namespace);
5799 if (memberType == NULL) {
5800 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
5801 "Union \"%s\" references an unknown member type \"%s\".\n",
5802 type->name, (const xmlChar *) tmp);
5803 } else {
5804 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
5805 xmlSchemaTypeFixup(memberType, ctxt, NULL);
5806 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
5807 if (link == NULL) {
5808 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
5809 return (-1);
5810 }
5811 link->type = memberType;
5812 link->next = NULL;
5813 if (lastLink == NULL)
5814 ctxtType->memberTypes = link;
5815 else
5816 lastLink->next = link;
5817 lastLink = link;
5818 }
5819 xmlFree(tmp);
5820 cur = end;
5821 } while (*cur != 0);
5822 }
5823 /*
5824 * Add local simple types,
5825 */
5826 memberType = type->subtypes;
5827 while (memberType != NULL) {
5828 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
5829 xmlSchemaTypeFixup(memberType, ctxt, NULL);
5830 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
5831 if (link == NULL) {
5832 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
5833 return (-1);
5834 }
5835 link->type = memberType;
5836 link->next = NULL;
5837 if (lastLink == NULL)
5838 ctxtType->memberTypes = link;
5839 else
5840 lastLink->next = link;
5841 lastLink = link;
5842 memberType = memberType->next;
5843 }
5844 /*
5845 * The actual value is then formed by replacing any union type
5846 * definition in the ·explicit members· with the members of their
5847 * {member type definitions}, in order.
5848 */
5849 link = ctxtType->memberTypes;
5850 while (link != NULL) {
5851 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
5852 subLink = link->type->memberTypes;
5853 if (subLink != NULL) {
5854 link->type = subLink->type;
5855 if (subLink->next != NULL) {
5856 lastLink = link->next;
5857 subLink = subLink->next;
5858 prevLink = link;
5859 while (subLink != NULL) {
5860 newLink = (xmlSchemaTypeLinkPtr)
5861 xmlMalloc(sizeof(xmlSchemaTypeLink));
5862 if (newLink == NULL) {
5863 xmlSchemaPErrMemory(ctxt, "allocating a type link",
5864 NULL);
5865 return (-1);
5866 }
5867 newLink->type = memberType;
5868 prevLink->next = newLink;
5869 prevLink = newLink;
5870 newLink->next = lastLink;
5871
5872 subLink = subLink->next;
5873 }
5874 }
5875 }
5876 }
5877 link = link->next;
5878 }
5879
5880 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005881}
5882
Daniel Veillard4255d502002-04-16 15:50:10 +00005883/**
Daniel Veillard3646d642004-06-02 19:19:14 +00005884 * xmlSchemaGetOnymousTypeName:
5885 * @attr: the attribute declaration/use
5886 *
5887 * Returns the name of the attribute; if the attribute
5888 * is a reference, the name of the referenced global type will be returned.
5889 */
5890static const xmlChar *
5891xmlSchemaGetOnymousAttrName(xmlSchemaAttributePtr attr)
5892{
5893 if (attr->ref != NULL)
5894 return(attr->ref);
5895 else
5896 return(attr->name);
5897}
5898
5899/**
5900 * xmlSchemaGetOnymousTargetNsURI:
5901 * @type: the type (element or attribute)
5902 *
5903 * Returns the target namespace URI of the type; if the type is a reference,
5904 * the target namespace of the referenced type will be returned.
5905 */
5906static const xmlChar *
5907xmlSchemaGetOnymousTargetNsURI(xmlSchemaTypePtr type)
5908{
5909 if (type->type == XML_SCHEMA_TYPE_ELEMENT) {
5910 if (type->ref != NULL)
5911 return(((xmlSchemaElementPtr)((xmlSchemaElementPtr)
5912 type)->subtypes)->targetNamespace);
5913 else
5914 return(((xmlSchemaElementPtr) type)->targetNamespace);
5915 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
5916 if (type->ref != NULL)
5917 return(((xmlSchemaAttributePtr)((xmlSchemaAttributePtr)
5918 type)->subtypes)->targetNamespace);
5919 else
5920 return(((xmlSchemaAttributePtr) type)->targetNamespace);
5921 } else
5922 return (NULL);
5923}
5924
5925/**
5926 * xmlSchemaIsDerivedFromBuiltInType:
5927 * @ctxt: the schema parser context
5928 * @type: the type definition
5929 * @valType: the value type
5930 *
5931 *
5932 * Returns 1 if the type has the given value type, or
5933 * is derived from such a type.
5934 */
William M. Brack803812b2004-06-03 02:11:24 +00005935static int
Daniel Veillard3646d642004-06-02 19:19:14 +00005936xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
5937 xmlSchemaTypePtr type, int valType)
5938{
5939 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005940 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00005941 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005942 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00005943 return(1);
5944 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
5945 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
5946 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
5947 ((xmlSchemaAttributePtr) type)->subtypes, valType));
5948 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
5949 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
5950 if (type->baseType != NULL)
5951 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
5952 valType));
5953 } else if ((type->subtypes != NULL) &&
5954 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
5955 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
5956 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
5957 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
5958 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
5959 valType));
5960 }
5961
5962 return (0);
5963}
5964
5965/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00005966 * xmlSchemaIsDerivedFromBuiltInType:
5967 * @type: the simpleType definition
5968 *
5969 * Returns the primitive type of the given type or
5970 * NULL in case of error.
5971 */
5972static xmlSchemaTypePtr
5973xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
5974{
5975 while (type != NULL) {
5976 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
5977 return (type);
5978 type = type->baseType;
5979 }
5980
5981 return (NULL);
5982}
5983
5984
5985/**
Daniel Veillard3646d642004-06-02 19:19:14 +00005986 * xmlSchemaBuildAttributeUsesOwned:
5987 * @ctxt: the schema parser context
5988 * @type: the complex type definition
5989 * @cur: the attribute declaration list
5990 * @lastUse: the top of the attribute use list
5991 *
5992 * Builds the attribute uses list on the given complex type.
5993 * This one is supposed to be called by
5994 * xmlSchemaBuildAttributeValidation only.
5995 */
5996static int
5997xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
5998 xmlSchemaAttributePtr cur,
5999 xmlSchemaAttributeLinkPtr *uses,
6000 xmlSchemaAttributeLinkPtr *lastUse)
6001{
6002 xmlSchemaAttributeLinkPtr tmp;
6003 while (cur != NULL) {
6004 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6005 /*
6006 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
6007 * to by the ·actual value·s of the ref [attribute] of the
6008 * <attributeGroup> [children], if any."
6009 */
6010 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
6011 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
6012 lastUse) == -1) {
6013 return (-1);
6014 }
6015 } else {
6016 /* W3C: "1 The set of attribute uses corresponding to the
6017 * <attribute> [children], if any."
6018 */
6019 tmp = (xmlSchemaAttributeLinkPtr)
6020 xmlMalloc(sizeof(xmlSchemaAttributeLink));
6021 if (tmp == NULL) {
6022 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
6023 return (-1);
6024 }
6025 tmp->attr = cur;
6026 tmp->next = NULL;
6027 if (*uses == NULL)
6028 *uses = tmp;
6029 else
6030 (*lastUse)->next = tmp;
6031 *lastUse = tmp;
6032 }
6033 cur = cur->next;
6034 }
6035 return (0);
6036}
6037
Daniel Veillard50355f02004-06-08 17:52:16 +00006038/**
6039 * xmlSchemaCloneWildcardNsConstraints:
6040 * @ctxt: the schema parser context
6041 * @dest: the destination wildcard
6042 * @source: the source wildcard
6043 *
6044 * Clones the namespace constraints of source
6045 * and assignes them to dest.
6046 * Returns -1 on internal error, 0 otherwise.
6047 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006048static int
6049xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
6050 xmlSchemaWildcardPtr *dest,
6051 xmlSchemaWildcardPtr source)
6052{
6053 xmlSchemaWildcardNsPtr cur, tmp, last;
6054
6055 if ((source == NULL) || (*dest == NULL))
6056 return(-1);
6057 (*dest)->any = source->any;
6058 cur = source->nsSet;
6059 last = NULL;
6060 while (cur != NULL) {
6061 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6062 if (tmp == NULL)
6063 return(-1);
6064 tmp->value = cur->value;
6065 if (last == NULL)
6066 (*dest)->nsSet = tmp;
6067 else
6068 last->next = tmp;
6069 last = tmp;
6070 cur = cur->next;
6071 }
6072 if ((*dest)->negNsSet != NULL)
6073 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
6074 if (source->negNsSet != NULL) {
6075 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6076 if ((*dest)->negNsSet == NULL)
6077 return(-1);
6078 (*dest)->negNsSet->value = source->negNsSet->value;
6079 } else
6080 (*dest)->negNsSet = NULL;
6081 return(0);
6082}
6083
Daniel Veillard50355f02004-06-08 17:52:16 +00006084/**
6085 * xmlSchemaUnionWildcards:
6086 * @ctxt: the schema parser context
6087 * @completeWild: the first wildcard
6088 * @curWild: the second wildcard
6089 *
6090 * Unions the namespace constraints of the given wildcards.
6091 * @completeWild will hold the resulting union.
6092 * Returns a positive error code on failure, -1 in case of an
6093 * internal error, 0 otherwise.
6094 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006095static int
6096xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
6097 xmlSchemaWildcardPtr completeWild,
6098 xmlSchemaWildcardPtr curWild)
6099{
6100 xmlSchemaWildcardNsPtr cur, curB, tmp;
6101
6102 /*
6103 * 1 If O1 and O2 are the same value, then that value must be the
6104 * value.
6105 */
6106 if ((completeWild->any == curWild->any) &&
6107 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
6108 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
6109
6110 if ((completeWild->negNsSet == NULL) ||
6111 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
6112
6113 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00006114 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00006115
6116 /*
6117 * Check equality of sets.
6118 */
6119 cur = completeWild->nsSet;
6120 while (cur != NULL) {
6121 found = 0;
6122 curB = curWild->nsSet;
6123 while (curB != NULL) {
6124 if (cur->value == curB->value) {
6125 found = 1;
6126 break;
6127 }
6128 curB = curB->next;
6129 }
6130 if (!found)
6131 break;
6132 cur = cur->next;
6133 }
6134 if (found)
6135 return(0);
6136 } else
6137 return(0);
6138 }
6139 }
6140 /*
6141 * 2 If either O1 or O2 is any, then any must be the value
6142 */
Daniel Veillard50355f02004-06-08 17:52:16 +00006143 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006144 if (completeWild->any == 0) {
6145 completeWild->any = 1;
6146 if (completeWild->nsSet != NULL) {
6147 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6148 completeWild->nsSet = NULL;
6149 }
6150 if (completeWild->negNsSet != NULL) {
6151 xmlFree(completeWild->negNsSet);
6152 completeWild->negNsSet = NULL;
6153 }
6154 }
Daniel Veillard50355f02004-06-08 17:52:16 +00006155 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00006156 }
6157 /*
6158 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
6159 * then the union of those sets must be the value.
6160 */
6161 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
6162 int found;
6163 xmlSchemaWildcardNsPtr start;
6164
6165 cur = curWild->nsSet;
6166 start = completeWild->nsSet;
6167 while (cur != NULL) {
6168 found = 0;
6169 curB = start;
6170 while (curB != NULL) {
6171 if (cur->value == curB->value) {
6172 found = 1;
6173 break;
6174 }
6175 curB = curB->next;
6176 }
6177 if (!found) {
6178 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6179 if (tmp == NULL)
6180 return (-1);
6181 tmp->value = cur->value;
6182 tmp->next = completeWild->nsSet;
6183 completeWild->nsSet = tmp;
6184 }
6185 cur = cur->next;
6186 }
6187
6188 return(0);
6189 }
6190 /*
6191 * 4 If the two are negations of different values (namespace names
6192 * or ·absent·), then a pair of not and ·absent· must be the value.
6193 */
6194 if ((completeWild->negNsSet != NULL) &&
6195 (curWild->negNsSet != NULL) &&
6196 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
6197 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00006198
6199 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00006200 }
6201 /*
6202 * 5.
6203 */
6204 if (((completeWild->negNsSet != NULL) &&
6205 (completeWild->negNsSet->value != NULL) &&
6206 (curWild->nsSet != NULL)) ||
6207 ((curWild->negNsSet != NULL) &&
6208 (curWild->negNsSet->value != NULL) &&
6209 (completeWild->nsSet != NULL))) {
6210
6211 int nsFound, absentFound = 0;
6212
6213 if (completeWild->nsSet != NULL) {
6214 cur = completeWild->nsSet;
6215 curB = curWild->negNsSet;
6216 } else {
6217 cur = curWild->nsSet;
6218 curB = completeWild->negNsSet;
6219 }
6220 nsFound = 0;
6221 while (cur != NULL) {
6222 if (cur->value == NULL)
6223 absentFound = 1;
6224 else if (cur->value == curB->value)
6225 nsFound = 1;
6226 if (nsFound && absentFound)
6227 break;
6228 cur = cur->next;
6229 }
6230
6231 if (nsFound && absentFound) {
6232 /*
6233 * 5.1 If the set S includes both the negated namespace
6234 * name and ·absent·, then any must be the value.
6235 */
6236 completeWild->any = 1;
6237 if (completeWild->nsSet != NULL) {
6238 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6239 completeWild->nsSet = NULL;
6240 }
6241 if (completeWild->negNsSet != NULL) {
6242 xmlFree(completeWild->negNsSet);
6243 completeWild->negNsSet = NULL;
6244 }
6245 } else if (nsFound && (!absentFound)) {
6246 /*
6247 * 5.2 If the set S includes the negated namespace name
6248 * but not ·absent·, then a pair of not and ·absent· must
6249 * be the value.
6250 */
6251 if (completeWild->nsSet != NULL) {
6252 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6253 completeWild->nsSet = NULL;
6254 }
6255 if (completeWild->negNsSet == NULL) {
6256 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6257 if (completeWild->negNsSet == NULL)
6258 return (-1);
6259 }
6260 completeWild->negNsSet->value = NULL;
6261 } else if ((!nsFound) && absentFound) {
6262 /*
6263 * 5.3 If the set S includes ·absent· but not the negated
6264 * namespace name, then the union is not expressible.
6265 */
6266 xmlSchemaPErr(ctxt, completeWild->node,
6267 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
6268 "The union of the wilcard is not expressible\n",
6269 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00006270 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00006271 } else if ((!nsFound) && (!absentFound)) {
6272 /*
6273 * 5.4 If the set S does not include either the negated namespace
6274 * name or ·absent·, then whichever of O1 or O2 is a pair of not
6275 * and a namespace name must be the value.
6276 */
6277 if (completeWild->negNsSet == NULL) {
6278 if (completeWild->nsSet != NULL) {
6279 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6280 completeWild->nsSet = NULL;
6281 }
6282 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6283 if (completeWild->negNsSet == NULL)
6284 return (-1);
6285 completeWild->negNsSet->value = curWild->negNsSet->value;
6286 }
6287 }
6288 return (0);
6289 }
6290 /*
6291 * 6.
6292 */
6293 if (((completeWild->negNsSet != NULL) &&
6294 (completeWild->negNsSet->value == NULL) &&
6295 (curWild->nsSet != NULL)) ||
6296 ((curWild->negNsSet != NULL) &&
6297 (curWild->negNsSet->value == NULL) &&
6298 (completeWild->nsSet != NULL))) {
6299
6300 if (completeWild->nsSet != NULL) {
6301 cur = completeWild->nsSet;
6302 } else {
6303 cur = curWild->nsSet;
6304 }
6305 while (cur != NULL) {
6306 if (cur->value == NULL) {
6307 /*
6308 * 6.1 If the set S includes ·absent·, then any must be the
6309 * value.
6310 */
6311 completeWild->any = 1;
6312 if (completeWild->nsSet != NULL) {
6313 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6314 completeWild->nsSet = NULL;
6315 }
6316 if (completeWild->negNsSet != NULL) {
6317 xmlFree(completeWild->negNsSet);
6318 completeWild->negNsSet = NULL;
6319 }
6320 return (0);
6321 }
6322 cur = cur->next;
6323 }
6324 if (completeWild->negNsSet == NULL) {
6325 /*
6326 * 6.2 If the set S does not include ·absent·, then a pair of not
6327 * and ·absent· must be the value.
6328 */
6329 if (completeWild->nsSet != NULL) {
6330 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6331 completeWild->nsSet = NULL;
6332 }
6333 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6334 if (completeWild->negNsSet == NULL)
6335 return (-1);
6336 completeWild->negNsSet->value = NULL;
6337 }
6338 return (0);
6339 }
6340 return (0);
6341
6342}
6343
Daniel Veillard50355f02004-06-08 17:52:16 +00006344/**
6345 * xmlSchemaIntersectWildcards:
6346 * @ctxt: the schema parser context
6347 * @completeWild: the first wildcard
6348 * @curWild: the second wildcard
6349 *
6350 * Intersects the namespace constraints of the given wildcards.
6351 * @completeWild will hold the resulting intersection.
6352 * Returns a positive error code on failure, -1 in case of an
6353 * internal error, 0 otherwise.
6354 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006355static int
6356xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
6357 xmlSchemaWildcardPtr completeWild,
6358 xmlSchemaWildcardPtr curWild)
6359{
William M. Brack803812b2004-06-03 02:11:24 +00006360 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00006361
6362 /*
6363 * 1 If O1 and O2 are the same value, then that value must be the
6364 * value.
6365 */
6366 if ((completeWild->any == curWild->any) &&
6367 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
6368 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
6369
6370 if ((completeWild->negNsSet == NULL) ||
6371 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
6372
6373 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00006374 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00006375
6376 /*
6377 * Check equality of sets.
6378 */
6379 cur = completeWild->nsSet;
6380 while (cur != NULL) {
6381 found = 0;
6382 curB = curWild->nsSet;
6383 while (curB != NULL) {
6384 if (cur->value == curB->value) {
6385 found = 1;
6386 break;
6387 }
6388 curB = curB->next;
6389 }
6390 if (!found)
6391 break;
6392 cur = cur->next;
6393 }
6394 if (found)
6395 return(0);
6396 } else
6397 return(0);
6398 }
6399 }
6400 /*
6401 * 2 If either O1 or O2 is any, then the other must be the value.
6402 */
6403 if ((completeWild->any != curWild->any) && (completeWild->any)) {
6404 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
6405 return(-1);
6406 return(0);
6407 }
6408 /*
6409 * 3 If either O1 or O2 is a pair of not and a value (a namespace
6410 * name or ·absent·) and the other is a set of (namespace names or
6411 * ·absent·), then that set, minus the negated value if it was in
6412 * the set, minus ·absent· if it was in the set, must be the value.
6413 */
6414 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
6415 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
6416 const xmlChar *neg;
6417
6418 if (completeWild->nsSet == NULL) {
6419 neg = completeWild->negNsSet->value;
6420 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
6421 return(-1);
6422 } else
6423 neg = curWild->negNsSet->value;
6424 /*
6425 * Remove absent and negated.
6426 */
6427 prev = NULL;
6428 cur = completeWild->nsSet;
6429 while (cur != NULL) {
6430 if (cur->value == NULL) {
6431 if (prev == NULL)
6432 completeWild->nsSet = cur->next;
6433 else
6434 prev->next = cur->next;
6435 xmlFree(cur);
6436 break;
6437 }
6438 prev = cur;
6439 cur = cur->next;
6440 }
6441 if (neg != NULL) {
6442 prev = NULL;
6443 cur = completeWild->nsSet;
6444 while (cur != NULL) {
6445 if (cur->value == neg) {
6446 if (prev == NULL)
6447 completeWild->nsSet = cur->next;
6448 else
6449 prev->next = cur->next;
6450 xmlFree(cur);
6451 break;
6452 }
6453 prev = cur;
6454 cur = cur->next;
6455 }
6456 }
6457
6458 return(0);
6459 }
6460 /*
6461 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
6462 * then the intersection of those sets must be the value.
6463 */
6464 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
6465 int found;
6466
6467 cur = completeWild->nsSet;
6468 prev = NULL;
6469 while (cur != NULL) {
6470 found = 0;
6471 curB = curWild->nsSet;
6472 while (curB != NULL) {
6473 if (cur->value == curB->value) {
6474 found = 1;
6475 break;
6476 }
6477 curB = curB->next;
6478 }
6479 if (!found) {
6480 if (prev == NULL)
6481 completeWild->nsSet = cur->next;
6482 else
6483 prev->next = cur->next;
6484 tmp = cur->next;
6485 xmlFree(cur);
6486 cur = tmp;
6487 continue;
6488 }
6489 prev = cur;
6490 cur = cur->next;
6491 }
6492
6493 return(0);
6494 }
6495 /* 5 If the two are negations of different namespace names,
6496 * then the intersection is not expressible
6497 */
6498 if ((completeWild->negNsSet != NULL) &&
6499 (curWild->negNsSet != NULL) &&
6500 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
6501 (completeWild->negNsSet->value != NULL) &&
6502 (curWild->negNsSet->value != NULL)) {
6503
6504 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
6505 "The intersection of the wilcard is not expressible\n",
6506 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00006507 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00006508 }
6509 /*
6510 * 6 If the one is a negation of a namespace name and the other
6511 * is a negation of ·absent·, then the one which is the negation
6512 * of a namespace name must be the value.
6513 */
6514 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
6515 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
6516 (completeWild->negNsSet->value == NULL)) {
6517 completeWild->negNsSet->value = curWild->negNsSet->value;
6518 }
6519 return(0);
6520}
6521
Daniel Veillard50355f02004-06-08 17:52:16 +00006522/**
6523 * xmlSchemaIsWildcardNsConstraintSubset:
6524 * @ctxt: the schema parser context
6525 * @wildA: the first wildcard
6526 * @wildB: the second wildcard
6527 *
6528 * Returns 1 if the namespace constraint of @wildA is an intensional
6529 * subset of @wildB, 0 otherwise.
6530 */
6531static int
6532xmlSchemaIsWildcardNsConstraintSubset(
6533 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
6534 xmlSchemaWildcardPtr wildA,
6535 xmlSchemaWildcardPtr wildB)
6536{
Daniel Veillard3646d642004-06-02 19:19:14 +00006537
Daniel Veillard50355f02004-06-08 17:52:16 +00006538 /*
6539 * Schema Component Constraint: Wildcard Subset
6540 */
6541 /*
6542 * 1 super must be any.
6543 */
6544 if (wildB->any)
6545 return (1);
6546 /*
6547 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
6548 * 2.2 super must be a pair of not and the same value.
6549 */
6550 if ((wildA->negNsSet != NULL) &&
6551 (wildB->negNsSet != NULL) &&
6552 (wildA->negNsSet->value == wildA->negNsSet->value))
6553 return (1);
6554 /*
6555 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
6556 */
6557 if (wildA->nsSet != NULL) {
6558 /*
6559 * 3.2.1 super must be the same set or a superset thereof.
6560 */
6561 if (wildB->nsSet != NULL) {
6562 xmlSchemaWildcardNsPtr cur, curB;
6563 int found = 0;
6564
6565 cur = wildA->nsSet;
6566 while (cur != NULL) {
6567 found = 0;
6568 curB = wildB->nsSet;
6569 while (curB != NULL) {
6570 if (cur->value == curB->value) {
6571 found = 1;
6572 break;
6573 }
6574 curB = curB->next;
6575 }
6576 if (!found)
6577 return (0);
6578 cur = cur->next;
6579 }
6580 if (found)
6581 return (1);
6582 } else if (wildB->negNsSet != NULL) {
6583 xmlSchemaWildcardNsPtr cur;
6584 /*
6585 * 3.2.2 super must be a pair of not and a namespace name or
6586 * ·absent· and that value must not be in sub's set.
6587 */
6588 cur = wildA->nsSet;
6589 while (cur != NULL) {
6590 if (cur->value == wildB->negNsSet->value)
6591 return (0);
6592 cur = cur->next;
6593 }
6594 return (1);
6595 }
6596 }
6597 return (0);
6598}
6599
6600/**
6601 * xmlSchemaBuildCompleteAttributeWildcard:
6602 * @ctxt: the schema parser context
6603 * @attrs: the attribute list
6604 * @completeWild: the resulting complete wildcard
6605 *
6606 * Returns -1 in case of an internal error, 0 otherwise.
6607 */
6608static int
6609xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
6610 xmlSchemaAttributePtr attrs,
6611 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00006612{
6613 while (attrs != NULL) {
6614 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6615 xmlSchemaAttributeGroupPtr group;
6616
6617 group = (xmlSchemaAttributeGroupPtr) attrs;
6618 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
6619 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00006620 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
6621 group->attributes, &group->attributeWildcard) == -1)
6622 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00006623 }
6624 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
6625 }
6626 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00006627 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006628 /*
6629 * Copy the first encountered wildcard as context, except for the annotation.
6630 */
Daniel Veillard50355f02004-06-08 17:52:16 +00006631 *completeWild = xmlSchemaAddWildcard(ctxt);
6632 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
6633 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
6634 completeWild, group->attributeWildcard) == -1)
6635 return (-1);
6636 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00006637 /*
6638 * Although the complete wildcard might not correspond to any
6639 * node in the schema, we will save this context node.
6640 */
Daniel Veillard50355f02004-06-08 17:52:16 +00006641 (*completeWild)->node = group->attributeWildcard->node;
6642
6643 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
6644 xmlSchemaFreeWildcard(*completeWild);
6645 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00006646 }
6647 }
6648 }
6649 attrs = attrs->next;
6650 }
6651
Daniel Veillard50355f02004-06-08 17:52:16 +00006652 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00006653}
6654
6655/**
6656 * xmlSchemaMatchesWildcardNs:
6657 * @wild: the wildcard
6658 * @ns: the namespace
6659 *
6660 *
6661 * Returns 1 if the given namespace matches the wildcard,
6662 * 0 otherwise.
6663 */
6664static int
6665xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
6666{
6667 if (wild == NULL)
6668 return(0);
6669
6670 if (wild->any)
6671 return(1);
6672 else if (wild->nsSet != NULL) {
6673 xmlSchemaWildcardNsPtr cur;
6674
6675 cur = wild->nsSet;
6676 while (cur != NULL) {
6677 if (xmlStrEqual(cur->value, ns))
6678 return(1);
6679 cur = cur->next;
6680 }
6681 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
6682 (!xmlStrEqual(wild->negNsSet->value, ns)))
6683 return(1);
6684
6685 return(0);
6686}
6687
6688/**
6689 * xmlSchemaBuildAttributeValidation:
6690 * @ctxt: the schema parser context
6691 * @type: the complex type definition
6692 *
6693 *
6694 * Builds the wildcard and the attribute uses on the given complex type.
6695 * Returns -1 if an internal error occurs, 0 otherwise.
6696 */
6697static int
6698xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
6699{
6700 xmlSchemaTypePtr baseType = NULL;
6701 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +00006702 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00006703 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006704 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +00006705 int baseIsAnyType = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00006706
Daniel Veillard01fa6152004-06-29 17:04:39 +00006707 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +00006708 /*
6709 * Complex Type Definition with complex content Schema Component.
6710 *
6711 * Attribute uses.
6712 */
6713 if (type->attributeUses != NULL) {
6714 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00006715 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +00006716 "attribute uses already builded.\n",
6717 NULL, NULL);
6718 return (-1);
6719 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006720 if (type->baseType == NULL) {
6721 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
6722 "Internal error: xmlSchemaBuildAttributeValidation: "
6723 "complex type \"%s\" has no base type.\n",
6724 type->name, NULL);
6725 return (-1);
6726 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006727 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) ||
6728 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006729
6730 baseType = type->baseType;
6731 if (baseType == NULL) {
6732 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
6733 "Internal error: xmlSchemaBuildAttributeValidation: "
6734 "type has no base type.\n",
6735 NULL, NULL);
6736 return (-1);
6737 }
6738
6739 if (baseType == anyType)
6740 baseIsAnyType = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00006741 /*
6742 * Inherit the attribute uses of the base type.
6743 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006744 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +00006745 * NOTE: It is allowed to "extend" the anyType complex type.
Daniel Veillard3646d642004-06-02 19:19:14 +00006746 */
6747 if (!baseIsAnyType) {
6748 if (baseType != NULL) {
6749 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
6750 tmp = (xmlSchemaAttributeLinkPtr)
6751 xmlMalloc(sizeof(xmlSchemaAttributeLink));
6752 if (tmp == NULL) {
6753 xmlSchemaPErrMemory(ctxt,
6754 "building attribute uses of complexType", NULL);
6755 return (-1);
6756 }
6757 tmp->attr = cur->attr;
6758 tmp->next = NULL;
6759 if (type->attributeUses == NULL) {
6760 type->attributeUses = tmp;
6761 } else
6762 lastBaseUse->next = tmp;
6763 lastBaseUse = tmp;
6764 }
6765 }
6766 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006767 if ((type->subtypes != NULL) &&
6768 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
6769 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
6770 attrs = type->subtypes->subtypes->attributes;
6771 type->attributeWildcard = type->subtypes->subtypes->attributeWildcard;
6772 } else {
6773 /* Short hand form of the complexType. */
6774 attrs = type->attributes;
6775 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006776 /*
6777 * Handle attribute wildcards.
Daniel Veillard50355f02004-06-08 17:52:16 +00006778 */
Daniel Veillard50355f02004-06-08 17:52:16 +00006779 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00006780 attrs, &type->attributeWildcard) == -1) {
Daniel Veillard50355f02004-06-08 17:52:16 +00006781 if ((type->attributeWildcard != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00006782 /* Either we used the short hand form... */
6783 ((type->subtypes == NULL) ||
6784 /* Or complexType -> restriction/extension */
6785 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
Daniel Veillard50355f02004-06-08 17:52:16 +00006786 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6787 return (-1);
6788 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006789 /*
6790 * TODO: This "onwed_attr_wildcard" is quite sensless: we should
6791 * create the wildcard right from the start on the complexType,
6792 * rather than on the <restriction>/<extension>.
6793 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006794 if ((type->attributeWildcard != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00006795 /* Either we used the short hand form... */
6796 ((type->subtypes == NULL) ||
6797 /* Or complexType -> restriction/extension */
6798 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
Daniel Veillard3646d642004-06-02 19:19:14 +00006799 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6800
6801 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00006802 ((baseIsAnyType) ||
6803 ((baseType != NULL) &&
6804 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
6805 (baseType->attributeWildcard != NULL)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006806 if (type->attributeWildcard != NULL) {
6807 /*
6808 * Union the complete wildcard with the base wildcard.
6809 */
6810 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
6811 baseType->attributeWildcard) == -1)
6812 return (-1);
6813 } else {
6814 /*
6815 * Just inherit the wildcard.
6816 */
6817 type->attributeWildcard = baseType->attributeWildcard;
6818 }
6819 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006820
6821 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
6822 if (type->attributeWildcard != NULL) {
6823 /*
6824 * Derivation Valid (Restriction, Complex)
6825 * 4.1 The {base type definition} must also have one.
Daniel Veillard50355f02004-06-08 17:52:16 +00006826 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006827 if (baseType->attributeWildcard == NULL) {
6828 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
6829 "The derived type \"%s\" has an attribute wildcard, "
6830 "but the base type \"%s\" does not have one.\n",
6831 type->name, baseType->name);
6832 return (1);
6833 } else if (xmlSchemaIsWildcardNsConstraintSubset(ctxt,
6834 type->attributeWildcard, baseType->attributeWildcard) == 0) {
6835 /* 4.2 */
6836 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
6837 "The wildcard in the derived type \"%s\" is not a valid "
6838 "subset of the one in the base type \"%s\".\n",
6839 type->name, baseType->name);
6840 return (1);
6841 }
6842 /* 4.3 Unless the {base type definition} is the ·ur-type
6843 * definition·, the complex type definition's {attribute
6844 * wildcard}'s {process contents} must be identical to or
6845 * stronger than the {base type definition}'s {attribute
6846 * wildcard}'s {process contents}, where strict is stronger
6847 * than lax is stronger than skip.
6848 */
6849 if ((type->baseType != anyType) &&
6850 (type->attributeWildcard->processContents <
6851 baseType->attributeWildcard->processContents)) {
6852 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
6853 "The process contents of the wildcard in the "
6854 "derived type \"%s\" is weaker than "
6855 "that in the base type \"%s\".\n",
6856 type->name, baseType->name);
6857 return (1);
6858 }
Daniel Veillard50355f02004-06-08 17:52:16 +00006859 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006860 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
6861 /*
6862 * Derivation Valid (Extension)
6863 * At this point the type and the base have both, either
6864 * no wildcard or a wildcard.
6865 */
6866 if ((baseType->attributeWildcard != NULL) &&
6867 (baseType->attributeWildcard != type->attributeWildcard)) {
6868 /* 1.3 */
6869 if (xmlSchemaIsWildcardNsConstraintSubset(ctxt,
6870 baseType->attributeWildcard, type->attributeWildcard) == 0) {
6871 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_COS_CT_EXTENDS_1_3,
6872 "The wildcard in the derived type \"%s\" is not a valid "
6873 "superset of the one in the base type \"%s\".\n",
6874 type->name, baseType->name);
6875 return (1);
6876 }
6877 }
6878 }
6879 }
6880 /*
6881 * Removed, since anyType was plugged into the derivation hierarchy.
6882 */
6883 /*
6884 else {
6885 *
Daniel Veillard3646d642004-06-02 19:19:14 +00006886 * Although the complexType is implicitely derived by "restriction"
6887 * from the ur-type, this is not (yet?) reflected by libxml2.
Daniel Veillard01fa6152004-06-29 17:04:39 +00006888 *
Daniel Veillard3646d642004-06-02 19:19:14 +00006889 baseType = NULL;
6890 attrs = type->attributes;
Daniel Veillard50355f02004-06-08 17:52:16 +00006891 if (attrs != NULL) {
6892 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
6893 attrs, &type->attributeWildcard) == -1) {
6894 if ((type->attributeWildcard != NULL) &&
6895 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard))
6896 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6897 return (-1);
6898 }
6899 if ((type->attributeWildcard != NULL) &&
6900 ((type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD) == 0))
6901 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6902 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006903 } */
Daniel Veillard3646d642004-06-02 19:19:14 +00006904 /*
6905 * Gather attribute uses defined by this type.
6906 */
6907 if (attrs != NULL) {
6908 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
6909 &uses, &lastUse) == -1) {
6910 return (-1);
6911 }
6912 }
6913 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
6914 * "Two distinct attribute declarations in the {attribute uses} must
6915 * not have identical {name}s and {target namespace}s."
6916 *
6917 * For "extension" this is done further down.
6918 */
6919 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
6920 cur = uses;
6921 while (cur != NULL) {
6922 tmp = cur->next;
6923 while (tmp != NULL) {
6924 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6925 xmlSchemaGetOnymousAttrName(tmp->attr))) &&
6926 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
6927 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
6928
6929 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
6930 "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
6931 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6932 break;
6933 }
6934 tmp = tmp->next;
6935 }
6936 cur = cur->next;
6937 }
6938 }
6939 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
6940 /*
6941 * Derive by restriction.
6942 */
6943 if (baseIsAnyType) {
6944 type->attributeUses = uses;
6945 } else {
6946 int found;
6947
6948 cur = uses;
6949 while (cur != NULL) {
6950 found = 0;
6951 base = type->attributeUses;
6952 while (base != NULL) {
6953 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6954 xmlSchemaGetOnymousAttrName(base->attr))) &&
6955 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr),
6956 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) base->attr)))) {
6957
6958 found = 1;
6959 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6960 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6961 /*
6962 * derivation-ok-restriction 2.1.1
6963 */
6964 xmlSchemaPErr(ctxt, cur->attr->node,
6965 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
6966 "derivation-ok-restriction.2.1.1: "
6967 "The \"optional\" attribute "
6968 "use \"%s\" is inconsistent with a matching "
6969 "\"required\" attribute use of the base type\n",
6970 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6971 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
6972 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6973 /*
6974 * derivation-ok-restriction 3
6975 */
6976 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
6977 "derivation-ok-restriction.3: "
6978 "The \"required\" attribute use \"%s\" of the base type "
6979 "does not have a matching attribute use in the derived type\n",
6980 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6981
6982 } else {
6983 /*
6984 * Override the attribute use.
6985 */
6986 base->attr = cur->attr;
6987 }
6988 /*
6989 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
Daniel Veillard50355f02004-06-08 17:52:16 +00006990 * TODO: derivation-ok-restriction 2.1.3
Daniel Veillard3646d642004-06-02 19:19:14 +00006991 */
6992 break;
6993 }
6994 base = base->next;
6995 }
6996
6997 if (!found) {
6998 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6999 /*
7000 * derivation-ok-restriction 2.2
7001 */
7002 if ((type->attributeWildcard != NULL) &&
7003 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
7004 cur->attr->targetNamespace))
7005 found = 1;
7006
7007 if (!found) {
7008 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
7009 "derivation-ok-restriction.2.2: "
7010 "The attribute use \"%s\" has neither a matching attribute use, "
7011 "nor a matching wildcard in the base type\n",
7012 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
7013 } else {
7014 /*
7015 * Add the attribute use.
7016 *
7017 * Note that this may lead to funny derivation error reports, if
7018 * multiple equal attribute uses exist; but this is not
7019 * allowed anyway, and it will be reported beforehand.
7020 */
7021 tmp = cur;
7022 if (prev != NULL)
7023 prev->next = cur->next;
7024 else
7025 uses = cur->next;
7026 cur = cur->next;
7027 if (type->attributeUses == NULL) {
7028 type->attributeUses = tmp;
7029 } else
7030 lastBaseUse->next = tmp;
7031 lastBaseUse = tmp;
7032
7033 continue;
7034 }
7035 }
7036 }
7037 prev = cur;
7038 cur = cur->next;
7039 }
7040 if (uses != NULL)
7041 xmlSchemaFreeAttributeUseList(uses);
7042 }
7043 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
7044 /*
7045 * The spec allows only appending, and not other kinds of extensions.
7046 *
7047 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
7048 */
7049 if (uses != NULL) {
7050 if (type->attributeUses == NULL) {
7051 type->attributeUses = uses;
7052 } else
7053 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00007054 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007055 } else {
7056 /*
Daniel Veillard50355f02004-06-08 17:52:16 +00007057 * Derive implicitely from the ur-type.
7058 */
Daniel Veillard3646d642004-06-02 19:19:14 +00007059 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00007060 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007061 /*
7062 * 3.4.6 -> Complex Type Definition Properties Correct
7063 */
7064 if (type->attributeUses != NULL) {
7065 cur = type->attributeUses;
7066 prev = NULL;
7067 while (cur != NULL) {
7068 /*
7069 * 4. Two distinct attribute declarations in the {attribute uses} must
7070 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +00007071 *
Daniel Veillard3646d642004-06-02 19:19:14 +00007072 * Note that this was already done for "restriction" and types derived from
7073 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +00007074 */
Daniel Veillard3646d642004-06-02 19:19:14 +00007075 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
7076 tmp = cur->next;
7077 while (tmp != NULL) {
7078 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
7079 xmlSchemaGetOnymousAttrName(tmp->attr))) &&
7080 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
7081 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
7082
7083 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
7084 "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
7085 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00007086 break;
7087 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007088 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00007089 }
7090 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007091 /*
7092 * 5. Two distinct attribute declarations in the {attribute uses} must
7093 * not have {type definition}s which are or are derived from ID.
7094 */
7095 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00007096 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007097 if (id != NULL) {
7098 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_5,
7099 "ct-props-correct.5: Two attribute declarations, "
7100 "\"%s\" and \"%s\" have types which derived from ID\n",
7101 xmlSchemaGetOnymousAttrName(id->attr),
7102 xmlSchemaGetOnymousAttrName(cur->attr));
Daniel Veillard50355f02004-06-08 17:52:16 +00007103 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007104 id = cur;
7105 }
7106 /*
7107 * Remove "prohibited" attribute uses. The reason this is done at this late
7108 * stage is to be able to catch dublicate attribute uses. So we had to keep
7109 * prohibited uses in the list as well.
7110 */
7111 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7112 tmp = cur;
7113 if (prev == NULL)
7114 type->attributeUses = cur->next;
7115 else
7116 prev->next = cur->next;
7117 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00007118 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +00007119 } else {
7120 prev = cur;
7121 cur = cur->next;
7122 }
7123 }
7124 }
7125 /*
7126 * TODO: This check should be removed if we are 100% sure of
7127 * the base type attribute uses already being built.
7128 */
7129 if ((baseType != NULL) && (!baseIsAnyType) &&
7130 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
7131 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
7132 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00007133 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +00007134 "attribute uses not builded on base type \"%s\".\n",
7135 baseType->name, NULL);
7136 }
7137 return (0);
7138}
7139
7140/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00007141 * xmlSchemaTypeFinalContains:
7142 * @schema: the schema
7143 * @type: the type definition
7144 * @final: the final
7145 *
7146 * Evaluates if a type definition contains the given "final".
7147 * This does take "finalDefault" into account as well.
7148 *
7149 * Returns 1 if the type does containt the given "final",
7150 * 0 otherwise.
7151 */
7152static int
7153xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
7154{
7155 int tfinal = final, tflags = type->flags;
7156
7157 if (type == NULL)
7158 return (0);
7159 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
7160 switch (final) {
7161 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
7162 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7163 break;
7164 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
7165 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7166 break;
7167 case XML_SCHEMAS_TYPE_FINAL_LIST:
7168 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
7169 break;
7170 case XML_SCHEMAS_TYPE_FINAL_UNION:
7171 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
7172 break;
7173 }
7174 tflags = schema->flags;
7175 }
7176 if (tflags & tfinal)
7177 return (1);
7178 else
7179 return (0);
7180
7181}
7182
7183/**
7184 * xmlSchemaGetUnionSimpleTypeMemberTypes:
7185 * @type: the Union Simple Type
7186 *
7187 * Returns a list of member types of @type if existing,
7188 * returns NULL otherwise.
7189 */
7190xmlSchemaTypeLinkPtr
7191xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
7192{
7193 while (type != NULL) {
7194 if (type->memberTypes != NULL)
7195 return (type->memberTypes);
7196 else
7197 type = type->baseType;
7198 }
7199 return (NULL);
7200}
7201
7202/**
7203 * xmlSchemaGetListSimpleTypeItemType:
7204 * @type: the simple type definition
7205 *
7206 * Returns the item type definition of the list simple type.
7207 */
7208static xmlSchemaTypePtr
7209xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
7210{
7211 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
7212 return (NULL);
7213 /*
7214 * Note: In libxml2, the built-in types do not reflect
7215 * the datatype hierarchy (yet?) - we have to treat them
7216 * in a special way.
7217 */
7218 if (type->type == XML_SCHEMA_TYPE_BASIC)
7219 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
7220 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
7221 /* 1 If the <list> alternative is chosen, then the type
7222 * definition ·resolved· to by the ·actual value· of the
7223 * itemType [attribute] of <list>, if present, otherwise
7224 * the type definition corresponding to the <simpleType>
7225 * among the [children] of <list>.
7226 */
7227 return (type->subtypes->subtypes);
7228 else {
7229 /* 2 If the <restriction> option is chosen, then the
7230 * {item type definition} of the {base type definition}.
7231 */
7232 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
7233 }
7234}
7235
7236/**
7237 * xmlSchemaCheckCOSSTDerivedOK:
7238 * @type: the derived simple type definition
7239 * @baseType: the base type definition
7240 *
7241 * Checks wheter @type can be validly
7242 * derived from @baseType.
7243 *
7244 * Returns 0 on success, an positive error code otherwise.
7245 */
7246static int
7247xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
7248 xmlSchemaTypePtr type,
7249 xmlSchemaTypePtr baseType,
7250 int subset)
7251{
7252 /*
7253 * Schema Component Constraint: Type Derivation OK (Simple)
7254 *
7255 *
7256 * 1 They are the same type definition.
7257 * TODO: The identy check might have to be more complex than this.
7258 */
7259 if (type == baseType)
7260 return (0);
7261 /*
7262 * 2.1 restriction is not in the subset, or in the {final}
7263 * of its own {base type definition};
7264 */
7265 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
7266 (xmlSchemaTypeFinalContains(schema,
7267 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
7268 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
7269 }
7270 /* 2.2 */
7271 if (type->baseType == baseType) {
7272 /*
7273 * 2.2.1 D's ·base type definition· is B.
7274 */
7275 return (0);
7276 }
7277 /*
7278 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
7279 * and is validly derived from B given the subset, as defined by this
7280 * constraint.
7281 */
7282 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
7283 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
7284 return (0);
7285 }
7286 /*
7287 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
7288 * definition·.
7289 */
7290 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
7291 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
7292 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
7293 return (0);
7294 }
7295 /*
7296 * 2.2.4 B's {variety} is union and D is validly derived from a type
7297 * definition in B's {member type definitions} given the subset, as
7298 * defined by this constraint.
7299 *
7300 * NOTE: This seems not to involve built-in types, since there is no
7301 * built-in Union Simple Type.
7302 */
7303 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
7304 xmlSchemaTypeLinkPtr cur;
7305
7306 cur = baseType->memberTypes;
7307 while (cur != NULL) {
7308 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
7309 cur->type, subset) == 0)
7310 return (0);
7311 cur = cur->next;
7312 }
7313 }
7314
7315 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
7316}
7317
7318
7319/**
7320 * xmlSchemaCheckSTPropsCorrect:
7321 * @ctxt: the schema parser context
7322 * @type: the simple type definition
7323 *
7324 * Checks st-props-correct.
7325 *
7326 * Returns 0 if the properties are correct,
7327 * if not, a positive error code and -1 on internal
7328 * errors.
7329 */
7330static int
7331xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
7332 xmlSchemaTypePtr type)
7333{
7334 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
7335 anyType;
7336
7337 /*
7338 * Schema Component Constraint: Simple Type Definition Properties Correct
7339 *
7340 * NOTE: This is somehow redundant, since we actually built a simple type
7341 * to have all the needed information; this acts as an self test.
7342 */
7343 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
7344 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
7345 /*
7346 * TODO: 1 The values of the properties of a simple type definition must be as
7347 * described in the property tableau in Datatype definition, modulo the
7348 * impact of Missing Sub-components (§5.3).
7349 */
7350 /* Base type: If the datatype has been ·derived· by ·restriction·
7351 * then the Simple Type Definition component from which it is ·derived·,
7352 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
7353 */
7354 if (baseType == NULL) {
7355 xmlSchemaPErr(ctxt, type->node,
7356 XML_SCHEMAP_ST_PROPS_CORRECT_1,
7357 "Simple type \"%s\" does not have a base type.\n",
7358 type->name, NULL);
7359 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
7360 }
7361 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
7362 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
7363 (baseType == anyType))) {
7364 xmlSchemaPErr(ctxt, type->node,
7365 XML_SCHEMAP_ST_PROPS_CORRECT_1,
7366 "Simple type \"%s\": its base type \"%s\" is not a simple "
7367 "type.\n",
7368 type->name, baseType->name);
7369 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
7370 }
7371 if ((baseType != anySimpleType) &&
7372 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
7373 xmlSchemaPErr(ctxt, type->node,
7374 XML_SCHEMAP_ST_PROPS_CORRECT_1,
7375 "Simple type \"%s\" (not derived by restriction) must have"
7376 "the simple ur-type definition as base type, not \"%s\".\n",
7377 type->name, NULL);
7378 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
7379 }
7380 /*
7381 * Variety: One of {atomic, list, union}.
7382 */
7383 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
7384 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
7385 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
7386 xmlSchemaPErr(ctxt, type->node,
7387 XML_SCHEMAP_ST_PROPS_CORRECT_1,
7388 "Simple type \"%s\" has an absent variety.\n",
7389 type->name, NULL);
7390 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
7391 }
7392 /* TODO: Finish this. */
7393
7394 /*
7395 * 2 All simple type definitions must be derived ultimately from the ·simple
7396 * ur-type definition (so· circular definitions are disallowed). That is, it
7397 * must be possible to reach a built-in primitive datatype or the ·simple
7398 * ur-type definition· by repeatedly following the {base type definition}.
7399 */
7400 baseType = type->baseType;
7401 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
7402 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
7403 xmlSchemaTypeFixup(baseType, ctxt, NULL);
7404 if (baseType == anySimpleType)
7405 break;
7406 else if (baseType == type) {
7407 xmlSchemaPErr(ctxt, type->node,
7408 XML_SCHEMAP_ST_PROPS_CORRECT_2,
7409 "Simple type \"%s\" is not derived from the simple "
7410 "ur-type definition (circular definitions are disallowed).\n",
7411 type->name, NULL);
7412 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
7413 }
7414 baseType = baseType->baseType;
7415 }
7416 /*
7417 * 3 The {final} of the {base type definition} must not contain restriction.
7418 */
7419 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
7420 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
7421 xmlSchemaPErr(ctxt, type->node,
7422 XML_SCHEMAP_ST_PROPS_CORRECT_3,
7423 "Simple type \"%s\": the \"final\" of its base type "
7424 "\"%s\" must not contain \"restriction\".\n",
7425 type->name, baseType->name);
7426 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
7427 }
7428 return (0);
7429}
7430
7431/**
7432 * xmlSchemaCheckDerivationValidSimpleRestriction:
7433 * @ctxt: the schema parser context
7434 * @type: the simple type definition
7435 *
7436 * Checks if the given @type (simpleType) is derived
7437 * validly by restriction.
7438 *
7439 * Returns -1 on internal errors, 0 if the type is validly derived,
7440 * a positive error code otherwise.
7441 */
7442static int
7443xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
7444 xmlSchemaTypePtr type)
7445{
7446
7447 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
7448 xmlSchemaPErr(ctxt, type->node,
7449 XML_ERR_INTERNAL_ERROR,
7450 "xmlSchemaCheckDerivationValidSimpleRestriction: the given "
7451 "type \"%s\" is not a user-derived simpleType.\n",
7452 type->name, NULL);
7453 return (-1);
7454 }
7455
7456 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
7457 xmlSchemaTypePtr primitive;
7458 /*
7459 * 1.1 The {base type definition} must be an atomic simple
7460 * type definition or a built-in primitive datatype.
7461 */
7462 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
7463 xmlSchemaPErr(ctxt, type->node,
7464 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
7465 "Atomic simple type \"%s\": "
7466 "its base type \"%s\" is not an atomic simple type.\n",
7467 type->name, NULL);
7468 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
7469 }
7470 /* 1.2 The {final} of the {base type definition} must not contain
7471 * restriction.
7472 */
7473 /* OPTIMIZE: This is already done in xmlSchemaCheckStPropsCorrect */
7474 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
7475 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
7476 xmlSchemaPErr(ctxt, type->node,
7477 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
7478 "Atomic simple type \"%s\": the \"final\" of its base type "
7479 "\"%s\" must not contain \"restriction\".\n",
7480 type->name, type->baseType->name);
7481 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
7482 }
7483
7484 /*
7485 * 1.3.1 DF must be an allowed constraining facet for the {primitive
7486 * type definition}, as specified in the appropriate subsection of 3.2
7487 * Primitive datatypes.
7488 */
7489 if (type->facets != NULL) {
7490 xmlSchemaFacetPtr facet;
7491 int ok = 1;
7492
7493 primitive = xmlSchemaGetPrimitiveType(type);
7494 if (primitive == NULL) {
7495 xmlSchemaPErr(ctxt, type->node,
7496 XML_ERR_INTERNAL_ERROR,
7497 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
7498 "to get primitive type of type \"%s\".\n",
7499 type->name, NULL);
7500 return (-1);
7501 }
7502 facet = type->facets;
7503 do {
7504 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
7505 xmlSchemaPErrExt(ctxt, type->node,
7506 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
7507 NULL, NULL, NULL,
7508 "Atomic simple type \"%s\": the facet \"%s\" "
7509 "is not allowed on primitive type \"%s\".\n",
7510 type->name,
7511 xmlSchemaFacetTypeToString(facet->type),
7512 primitive->name, NULL, NULL);
7513
7514 ok = 0;
7515 }
7516 facet = facet->next;
7517 } while (facet != NULL);
7518 if (ok == 0)
7519 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
7520
7521 }
7522 /*
7523 * TODO: 1.3.2 (facet derivation)
7524 */
7525 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
7526 xmlSchemaTypePtr itemType = NULL;
7527
7528 itemType = xmlSchemaGetListSimpleTypeItemType(type);
7529 if (itemType == NULL) {
7530 xmlSchemaPErr(ctxt, type->node,
7531 XML_ERR_INTERNAL_ERROR,
7532 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
7533 "failed to evaluate the item type of type \"%s\".\n",
7534 type->name, NULL);
7535 return (-1);
7536 }
7537 /*
7538 * 2.1 The {item type definition} must have a {variety} of atomic or
7539 * union (in which case all the {member type definitions}
7540 * must be atomic).
7541 */
7542 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
7543 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
7544 xmlSchemaPErr(ctxt, type->node,
7545 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
7546 "List simple type \"%s\": its item type \"%s\" "
7547 "is not an atomic or union simple type.\n",
7548 type->name, itemType->name);
7549 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
7550 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
7551 xmlSchemaTypeLinkPtr member;
7552
7553 member = itemType->memberTypes;
7554 while (member != NULL) {
7555 if ((member->type->flags &
7556 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
7557 xmlSchemaPErr(ctxt, type->node,
7558 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
7559 "List simple type \"%s\": its item type "
7560 "is a union simple type, but the member type "
7561 "\"%s\" of this item type is not an \"atomic\" "
7562 "simple type.\n",
7563 type->name, member->type->name);
7564 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
7565 }
7566 member = member->next;
7567 }
7568 }
7569
7570 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
7571 xmlSchemaFacetPtr facet;
7572 /*
7573 * This is the case if we have: <simpleType><list ..
7574 */
7575 /*
7576 * 2.3.1
7577 * 2.3.1.1 The {final} of the {item type definition} must not
7578 * contain list.
7579 */
7580 if (xmlSchemaTypeFinalContains(ctxt->schema,
7581 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
7582 xmlSchemaPErr(ctxt, type->node,
7583 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
7584 "List simple type \"%s\": the \"final\" of its item type "
7585 "\"%s\" must not contain \"list\".\n",
7586 type->name, itemType->name);
7587 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
7588 }
7589 /*
7590 * 2.3.1.2 The {facets} must only contain the whiteSpace
7591 * facet component.
7592 */
7593 if (type->facets != NULL) {
7594 facet = type->facets;
7595 do {
7596 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
7597 xmlSchemaPErr(ctxt, type->node,
7598 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
7599 "List simple type \"%s\": the facet \"%s\" "
7600 "is not allowed.\n",
7601 type->name, xmlSchemaFacetTypeToString(facet->type));
7602 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
7603 }
7604 facet = facet->next;
7605 } while (facet != NULL);
7606 }
7607 /*
7608 * TODO: Datatypes states:
7609 * A ·list· datatype can be ·derived· from an ·atomic· datatype
7610 * whose ·lexical space· allows space (such as string or anyURI)or
7611 * a ·union· datatype any of whose {member type definitions}'s
7612 * ·lexical space· allows space.
7613 */
7614 } else {
7615 /*
7616 * This is the case if we have: <simpleType><restriction ...
7617 */
7618 /*
7619 * 2.3.2
7620 * 2.3.2.1 The {base type definition} must have a {variety} of list.
7621 */
7622 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
7623 xmlSchemaPErr(ctxt, type->node,
7624 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
7625 "List simple type \"%s\": its base type \"%s\" must "
7626 "have a variety of list.\n",
7627 type->name, type->baseType->name);
7628 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
7629 }
7630 /*
7631 * 2.3.2.2 The {final} of the {base type definition} must not
7632 * contain restriction.
7633 */
7634 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
7635 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
7636 xmlSchemaPErr(ctxt, type->node,
7637 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
7638 "List simple type \"%s\": its base type \"%s\" must not "
7639 "have a \"final\" containing \"restriction\".\n",
7640 type->name, type->baseType->name);
7641 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
7642 }
7643 /*
7644 * 2.3.2.3 The {item type definition} must be validly derived
7645 * from the {base type definition}'s {item type definition} given
7646 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
7647 */
7648 {
7649 xmlSchemaTypePtr baseItemType;
7650
7651 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
7652 if (baseItemType == NULL) {
7653 xmlSchemaPErr(ctxt, type->node,
7654 XML_ERR_INTERNAL_ERROR,
7655 "xmlSchemaCheckDerivationValidSimpleRestriction: "
7656 "List simple type \"%s\": failed to "
7657 "evaluate the item type of its base type \"%s\".\n",
7658 type->name, type->baseType->name);
7659 return (-1);
7660 }
7661 if ((itemType != baseItemType) &&
7662 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
7663 baseItemType, 0) != 0)) {
7664 xmlSchemaPErrExt(ctxt, type->node,
7665 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3, NULL, NULL, NULL,
7666 "List simple type \"%s\": its item type \"%s\" is not "
7667 "validly derived from the item type \"%s\" of the "
7668 "base type \"%s\" as defined in Type Derivation OK "
7669 "(Simple).\n",
7670 type->name, itemType->name, baseItemType->name,
7671 type->baseType->name, NULL);
7672 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
7673 }
7674 }
7675
7676 if (type->facets != NULL) {
7677 xmlSchemaFacetPtr facet;
7678 int ok = 1;
7679 /*
7680 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
7681 * and enumeration facet components are allowed among the {facets}.
7682 */
7683 facet = type->facets;
7684 do {
7685 switch (facet->type) {
7686 case XML_SCHEMA_FACET_LENGTH:
7687 case XML_SCHEMA_FACET_MINLENGTH:
7688 case XML_SCHEMA_FACET_MAXLENGTH:
7689 case XML_SCHEMA_FACET_WHITESPACE:
7690 /*
7691 * TODO: 2.5.1.2 List datatypes
7692 * The value of ·whiteSpace· is fixed to the value collapse.
7693 */
7694 case XML_SCHEMA_FACET_PATTERN:
7695 case XML_SCHEMA_FACET_ENUMERATION:
7696 break;
7697 default: {
7698 xmlSchemaPErr(ctxt, type->node,
7699 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
7700 "List simple type \"%s\": the facet \"%s\" "
7701 "is not allowed.\n",
7702 type->name,
7703 xmlSchemaFacetTypeToString(facet->type));
7704 /*
7705 * We could return, but it's nicer to report all
7706 * invalid facets.
7707 */
7708 ok = 0;
7709 }
7710 }
7711 facet = facet->next;
7712 } while (facet != NULL);
7713 if (ok == 0)
7714 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
7715 /*
7716 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
7717 * is a facet of the same kind in the {facets} of the {base type
7718 * definition} (call this BF),then the DF's {value} must be a valid
7719 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
7720 */
7721 }
7722
7723
7724 }
7725 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
7726 /*
7727 * 3.1 The {member type definitions} must all have {variety} of
7728 * atomic or list.
7729 */
7730 xmlSchemaTypeLinkPtr member;
7731
7732 member = type->memberTypes;
7733 while (member != NULL) {
7734 if (((member->type->flags &
7735 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
7736 ((member->type->flags &
7737 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
7738 xmlSchemaPErr(ctxt, type->node,
7739 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
7740 "Union simple type \"%s\": the member type "
7741 "\"%s\" is not an \"atomic\" simple type.\n",
7742 type->name, member->type->name);
7743 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
7744 }
7745 member = member->next;
7746 }
7747 /*
7748 * 3.3.1 If the {base type definition} is the ·simple ur-type
7749 * definition·
7750 */
7751 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
7752 /*
7753 * 3.3.1.1 All of the {member type definitions} must have a
7754 * {final} which does not contain union.
7755 */
7756 member = type->memberTypes;
7757 while (member != NULL) {
7758 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
7759 XML_SCHEMAS_TYPE_FINAL_UNION)) {
7760 xmlSchemaPErr(ctxt, type->node,
7761 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
7762 "Union simple type \"%s\": the \"final\" of member type "
7763 "\"%s\" contains \"union\".\n",
7764 type->name, member->type->name);
7765 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
7766 }
7767 member = member->next;
7768 }
7769 /*
7770 * 3.3.1.2 The {facets} must be empty.
7771 */
7772 if (type->facetSet != NULL) {
7773 xmlSchemaPErr(ctxt, type->node,
7774 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
7775 "Union simple type \"%s\": the facets must be empty.\n",
7776 type->name, NULL);
7777 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
7778 }
7779 } else {
7780 /*
7781 * 3.3.2.1 The {base type definition} must have a {variety} of union.
7782 */
7783 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
7784 xmlSchemaPErr(ctxt, type->node,
7785 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
7786 "Union simple type \"%s\": its base type \"%s\" has not a "
7787 "variety of union.\n",
7788 type->name, type->baseType->name);
7789 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
7790 }
7791 /*
7792 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
7793 */
7794 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
7795 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
7796 xmlSchemaPErr(ctxt, type->node,
7797 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
7798 "Union simple type \"%s\": the \"final\" of its base "
7799 "type \"%s\" must not contain \"restriction\".\n",
7800 type->name, type->baseType->name);
7801 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
7802 }
7803 /*
7804 * 3.3.2.3 The {member type definitions}, in order, must be validly
7805 * derived from the corresponding type definitions in the {base
7806 * type definition}'s {member type definitions} given the empty set,
7807 * as defined in Type Derivation OK (Simple) (§3.14.6).
7808 */
7809 {
7810 xmlSchemaTypeLinkPtr baseMember;
7811
7812 /*
7813 * OPTIMIZE: if the type is restricting, it has no local defined
7814 * member types and inherits the member types of the base type;
7815 * thus a check for equality can be skipped.
7816 */
7817 /*
7818 * TODO: Even worse: I cannot see a scenario where a restricting
7819 * union simple type can have other member types as the member
7820 * types of it's base type. This check seems not necessary with
7821 * respect to the derivation process in libxml2.
7822 */
7823 if (type->memberTypes != NULL) {
7824 member = type->memberTypes;
7825 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
7826 if ((member == NULL) && (baseMember != NULL)) {
7827 xmlSchemaPErr(ctxt, type->node,
7828 XML_SCHEMAS_ERR_INTERNAL,
7829 "Internal error: "
7830 "xmlSchemaCheckDerivationValidSimpleRestriction "
7831 "(3.3.2.3), union simple type \"%s\", unequal number "
7832 "of member types in the base type\n",
7833 type->name, NULL);
7834 }
7835 while (member != NULL) {
7836 if (baseMember == NULL) {
7837 xmlSchemaPErr(ctxt, type->node,
7838 XML_SCHEMAS_ERR_INTERNAL,
7839 "Internal error: "
7840 "xmlSchemaCheckDerivationValidSimpleRestriction "
7841 "(3.3.2.3), union simple type \"%s\", unequal number "
7842 "of member types in the base type\n",
7843 type->name, NULL);
7844 }
7845 if ((member->type != baseMember->type) &&
7846 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
7847 member->type, baseMember->type, 0) != 0)) {
7848 xmlSchemaPErrExt(ctxt, type->node,
7849 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3, NULL,
7850 NULL, NULL,
7851 "Union simple type \"%s\": its member type "
7852 "\"%s\" is not validly derived from its "
7853 "corresponding member type \"%s\" of the base "
7854 "type \"%s\" as defined in Type Derivation OK "
7855 "(Simple).\n",
7856 type->name, member->type->name,
7857 baseMember->type->name,
7858 type->baseType->name, NULL);
7859 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
7860 }
7861 member = member->next;
7862 baseMember = baseMember->next;
7863 }
7864 }
7865 }
7866 /*
7867 * 3.3.2.4 Only pattern and enumeration facet components are
7868 * allowed among the {facets}.
7869 */
7870 if (type->facets != NULL) {
7871 xmlSchemaFacetPtr facet;
7872 int ok = 1;
7873
7874 facet = type->facets;
7875 do {
7876 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
7877 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
7878 xmlSchemaPErr(ctxt, type->node,
7879 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
7880 "Union simple type \"%s\": the facet \"%s\" "
7881 "is not allowed.\n",
7882 type->name,
7883 xmlSchemaFacetTypeToString(facet->type));
7884 ok = 0;
7885 }
7886 facet = facet->next;
7887 } while (facet != NULL);
7888 if (ok == 0)
7889 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
7890
7891 }
7892 /*
7893 * TODO: 3.3.2.5 (facet derivation)
7894 */
7895 }
7896 }
7897
7898 return (0);
7899}
7900
7901/**
7902 * xmlSchemaCheckSRCSimpleType:
7903 * @ctxt: the schema parser context
7904 * @type: the simple type definition
7905 *
7906 * Checks crc-simple-type constraints.
7907 *
7908 * Returns 0 if the constraints are satisfied,
7909 * if not a positive error code and -1 on internal
7910 * errors.
7911 */
7912static int
7913xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
7914 xmlSchemaTypePtr type)
7915{
7916 /*
7917 * NOTE: src-simple-type 2-4 are redundant, since the checks
7918 * were are done for the corresponding <restriction>, <list> and <union>
7919 * elements, but W3C wants a <simpleType> error as well, so it gets one.
7920 * Maby this can be skipped in the future, if we get sure it's not needed.
7921 */
7922 if (type->subtypes == NULL) {
7923 xmlSchemaPErr(ctxt, type->node,
7924 XML_SCHEMAS_ERR_INTERNAL,
7925 "Internal error: xmlSchemaCheckSRCSimpleType, "
7926 "no subtype on simple type \"%s\".\n",
7927 type->name, NULL);
7928 return (-1);
7929 }
7930 /*
7931 * src-simple-type.1 The corresponding simple type definition, if any,
7932 * must satisfy the conditions set out in Constraints on Simple Type
7933 * Definition Schema Components (§3.14.6).
7934 */
7935 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
7936 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
7937 /*
7938 * TODO: Removed this, since it got annoying to get an
7939 * extra error report, if anything failed until now.
7940 * Enable this if needed.
7941 */
7942 /*
7943 xmlSchemaPErr(ctxt, type->node,
7944 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
7945 "Simple type \"%s\" does not satisfy the constraints "
7946 "on simple type definitions.\n",
7947 type->name, NULL);
7948 */
7949 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
7950 }
7951
7952 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
7953 /*
7954 * src-simple-type.2 If the <restriction> alternative is chosen,
7955 * either it must have a base [attribute] or a <simpleType> among its
7956 * [children], but not both.
7957 */
7958 if (((type->subtypes->base == NULL) &&
7959 ((type->subtypes->subtypes == NULL) ||
7960 (type->subtypes->subtypes->type != XML_SCHEMA_TYPE_SIMPLE))) ||
7961 ((type->subtypes->base != NULL) &&
7962 (type->subtypes->subtypes != NULL) &&
7963 (type->subtypes->subtypes->type == XML_SCHEMA_TYPE_SIMPLE))) {
7964 xmlSchemaPErr(ctxt, type->node,
7965 XML_SCHEMAP_SRC_SIMPLE_TYPE_2,
7966 "Simple type \"%s\": "
7967 "The <restriction> alternative is chosen, thus either the "
7968 "\"base\" attribute or the <simpleType> child "
7969 "must be present, but not both.\n",
7970 type->name, NULL);
7971 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_2);
7972 }
7973 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
7974 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
7975 * an itemType [attribute] or a <simpleType> among its [children],
7976 * but not both.
7977 * NOTE: baseType is set to the local simple type definiton,
7978 * if existent, at parse time. This is a hack and not nice.
7979 */
7980 if (((type->subtypes->base == NULL) &&
7981 (type->baseType == NULL)) ||
7982 ((type->subtypes->base != NULL) &&
7983 (type->subtypes->baseType != NULL))) {
7984 xmlSchemaPErr(ctxt, type->node,
7985 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
7986 "Simple type \"%s\": "
7987 "The <list> alternative is chosen, thus either the "
7988 "\"itemType\" attribute or the <simpleType> child "
7989 "must be present, but not both.\n",
7990 type->name, NULL);
7991 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
7992 }
7993
7994
7995 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
7996 xmlSchemaTypeLinkPtr member;
7997 xmlSchemaTypePtr ancestor, anySimpleType;
7998
7999 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8000
8001 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
8002 * the <union> alternative is chosen, there must not be any entries
8003 * in the memberTypes [attribute] at any depth which resolve to the
8004 * component corresponding to the <simpleType>.
8005 */
8006 member = type->memberTypes;
8007 while (member != NULL) {
8008 ancestor = member->type;
8009 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
8010 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8011 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
8012 if (ancestor == anySimpleType)
8013 break;
8014 else if (ancestor == type) {
8015 xmlSchemaPErr(ctxt, type->node,
8016 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
8017 "Simple type \"%s\" is not derived from the simple "
8018 "ur-type definition (circular definitions are disallowed).\n",
8019 type->name, NULL);
8020 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
8021 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
8022 /*
8023 * TODO: Although a list simple type must not have a union ST
8024 * type as item type, which in turn has a list ST as member
8025 * type, we will assume this here as well, since this check
8026 * was not yet performed.
8027 */
8028
8029 }
8030 ancestor = ancestor->baseType;
8031 }
8032 member = member->next;
8033 }
8034
8035 }
8036
8037 return (0);
8038}
8039
8040/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008041 * xmlSchemaTypeFixup:
8042 * @typeDecl: the schema type definition
8043 * @ctxt: the schema parser context
8044 *
8045 * Fixes the content model of the type.
8046 */
8047static void
8048xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008049 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00008050{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008051 xmlSchemaTypePtr ctxtType;
8052
Daniel Veillard82bbbd42003-05-11 20:16:09 +00008053 if (typeDecl == NULL)
8054 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008055 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008056 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008057 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008058 switch (typeDecl->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008059 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
8060 if (typeDecl->subtypes != NULL) {
8061 if (typeDecl->subtypes->contentType ==
8062 XML_SCHEMA_CONTENT_UNKNOWN) {
8063 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
8064 NULL);
8065 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008066 typeDecl->contentType =
8067 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008068 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008069 break;
8070 }
8071 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008072 xmlSchemaTypePtr base = NULL;
8073
8074 ctxt->ctxtType->flags |=
8075 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008076 if (typeDecl->subtypes != NULL)
8077 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008078
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008079 if (typeDecl->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008080 base =
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008081 xmlSchemaGetType(ctxt->schema, typeDecl->base,
8082 typeDecl->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008083 if (base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008084 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008085 XML_SCHEMAP_SRC_RESOLVE,
8086 "Restriction \"%s\": the QName \"%s\" of the "
8087 "attribute \"base\" does not resolve to a schema "
8088 "component.\n",
8089 name, typeDecl->base);
8090 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +00008091 XML_SCHEMA_CONTENT_UNKNOWN) {
8092 /*
8093 * The base type might be not "type fixed" yet,
8094 * so do it now. */
8095 /*
8096 * TODO: Is a check for circular derivation already
8097 * done?
8098 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008099 xmlSchemaTypeFixup(base, ctxt, NULL);
8100 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008101 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008102 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8103 /*
8104 * ComplexType restriction.
8105 */
8106 /*
8107 * Base type: The type definition ·resolved· to by the ·actual
8108 * value· of the base [attribute]
8109 */
8110 ctxt->ctxtType->baseType = base;
8111 /*
8112 * Content type.
8113 */
8114 if (typeDecl->subtypes == NULL)
8115 /* 1.1.1 */
8116 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
8117 else if ((typeDecl->subtypes->subtypes == NULL) &&
8118 ((typeDecl->subtypes->type ==
8119 XML_SCHEMA_TYPE_ALL)
8120 || (typeDecl->subtypes->type ==
8121 XML_SCHEMA_TYPE_SEQUENCE)))
8122 /* 1.1.2 */
8123 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
8124 else if ((typeDecl->subtypes->type ==
8125 XML_SCHEMA_TYPE_CHOICE)
8126 && (typeDecl->subtypes->subtypes == NULL))
8127 /* 1.1.3 */
8128 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
8129 else {
8130 /* 1.2 and 2.X are applied at the other layer */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008131 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +00008132 XML_SCHEMA_CONTENT_ELEMENTS;
8133 }
8134 } else {
8135 /*
8136 * SimpleType restriction.
8137 */
8138 /* Base type:
8139 * The Simple Type Definition component resolved to by
8140 * the actual value of the base [attribute] or the
8141 * <simpleType> [children], whichever is present.
8142 */
8143 if ((base == NULL) && (typeDecl->subtypes != NULL)) {
8144 base = typeDecl->subtypes;
8145 ctxt->ctxtType->baseType = base;
8146 if (base->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8147 xmlSchemaTypeFixup(base, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008148 } else
Daniel Veillard01fa6152004-06-29 17:04:39 +00008149 ctxt->ctxtType->baseType = base;
8150
8151 if (((typeDecl->base == NULL) &&
8152 ((typeDecl->subtypes == NULL) ||
8153 (typeDecl->subtypes->type != XML_SCHEMA_TYPE_SIMPLE))) ||
8154 ((typeDecl->base != NULL) &&
8155 (typeDecl->subtypes != NULL) &&
8156 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SIMPLE))) {
8157 /*
8158 * src-restriction-base-or-simpleType
8159 * Either the base [attribute] or the simpleType [child] of the
8160 * <restriction> element must be present, but not both.
8161 */
8162 xmlSchemaPErr(ctxt, typeDecl->node,
8163 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8164 "Restriction \"%s\": "
8165 "Either the \"base\" attribute or the <simpleType> child "
8166 "must be present, but not both.\n",
8167 typeDecl->name, NULL);
8168 }
8169 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008170 break;
8171 }
8172 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008173 xmlSchemaTypePtr base = NULL;
8174 xmlSchemaContentType explicitContentType;
8175
8176 /*
8177 * An extension does exist on a complexType only.
8178 */
8179 ctxt->ctxtType->flags |=
8180 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
8181 if (typeDecl->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008182 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillard2582a332004-04-18 19:49:46 +00008183 xmlSchemaPErr(ctxt, typeDecl->node,
8184 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8185 "Schemas: extension type %s is recursive\n",
8186 name, NULL);
8187 return;
8188 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008189 if (typeDecl->base != NULL) {
8190 base =
8191 xmlSchemaGetType(ctxt->schema, typeDecl->base,
8192 typeDecl->baseNs);
8193 if (base == NULL) {
8194 xmlSchemaPErr(ctxt, typeDecl->node,
8195 XML_SCHEMAP_SRC_RESOLVE,
8196 "Extension \"%s\": the QName \"%s\" of the "
8197 "attribute \"base\" does not resolve to a schema "
8198 "component.\n",
8199 name, typeDecl->base);
8200 } else if (base->contentType ==
8201 XML_SCHEMA_CONTENT_UNKNOWN) {
8202 typeDecl->recurse = 1;
8203 xmlSchemaTypeFixup(base, ctxt, NULL);
8204 typeDecl->recurse = 0;
8205 }
8206 /*
8207 * The type definition ·resolved· to by the ·actual
8208 * value· of the base [attribute]
8209 */
8210 ctxt->ctxtType->baseType = base;
8211 /*
8212 * TODO: This one is still needed for computation of
8213 * the content model by xmlSchemaBuildAContentModel.
8214 * Try to get rid of it.
8215 */
8216 typeDecl->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008217 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008218 if ((typeDecl->subtypes != NULL) &&
8219 (typeDecl->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
8220 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
8221
8222 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
8223 if (typeDecl->subtypes == NULL)
8224 /* 1.1.1 */
8225 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
8226 else if ((typeDecl->subtypes->subtypes == NULL) &&
8227 ((typeDecl->subtypes->type ==
8228 XML_SCHEMA_TYPE_ALL)
8229 || (typeDecl->subtypes->type ==
8230 XML_SCHEMA_TYPE_SEQUENCE)))
8231 /* 1.1.2 */
8232 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
8233 else if ((typeDecl->subtypes->type ==
8234 XML_SCHEMA_TYPE_CHOICE)
8235 && (typeDecl->subtypes->subtypes == NULL))
8236 /* 1.1.3 */
8237 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
8238 if (base != NULL) {
8239 /* It will be reported later, if the base is missing. */
8240 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
8241 /* 2.1 */
8242 typeDecl->contentType = base->contentType;
8243 } else if (base->contentType ==
8244 XML_SCHEMA_CONTENT_EMPTY) {
8245 /* 2.2 imbitable ! */
8246 typeDecl->contentType =
8247 XML_SCHEMA_CONTENT_ELEMENTS;
8248 } else {
8249 /* 2.3 imbitable pareil ! */
8250 typeDecl->contentType =
8251 XML_SCHEMA_CONTENT_ELEMENTS;
8252 }
8253 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008254 break;
8255 }
8256 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008257 if ((typeDecl->subtypes == NULL) ||
8258 ((typeDecl->subtypes->type !=
8259 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
8260 (typeDecl->subtypes->type !=
8261 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
8262 /*
8263 * This case is understood as shorthand for complex
8264 * content restricting the ur-type definition, and
8265 * the details of the mappings should be modified as
8266 * necessary.
8267 */
8268 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
8269 typeDecl->flags |=
8270 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
8271 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008272 if (typeDecl->subtypes == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008273 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00008274 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
8275 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +00008276 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008277 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008278 if ((typeDecl->subtypes != NULL) &&
8279 (typeDecl->subtypes->contentType ==
8280 XML_SCHEMA_CONTENT_UNKNOWN)) {
8281 ctxtType = ctxt->ctxtType;
8282 ctxt->ctxtType = typeDecl;
8283 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
8284 NULL);
8285 ctxt->ctxtType = ctxtType;
8286 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008287 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008288 typeDecl->contentType =
8289 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008290 } else {
8291 if (typeDecl->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008292 typeDecl->contentType =
8293 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008294 }
8295 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008296 }
8297 xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008298 break;
8299 }
8300 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
8301 if (typeDecl->subtypes == NULL) {
8302 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00008303 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
8304 typeDecl->contentType =
8305 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008306 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00008307 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008308 typeDecl->contentType =
8309 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +00008310 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008311 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
8312 NULL);
8313 if (typeDecl->subtypes != NULL)
8314 typeDecl->contentType =
8315 typeDecl->subtypes->contentType;
8316 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008317 /*
8318 * Removed due to implementation of the build of attribute uses.
8319 */
8320 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00008321 if (typeDecl->attributes == NULL)
8322 typeDecl->attributes =
8323 typeDecl->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +00008324 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008325 }
8326 break;
8327 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008328 case XML_SCHEMA_TYPE_SIMPLE:
8329 /*
8330 * Simple Type Definition Schema Component
8331 *
8332 */
8333 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
8334 if (typeDecl->subtypes->contentType ==
8335 XML_SCHEMA_CONTENT_UNKNOWN) {
8336 ctxtType = ctxt->ctxtType;
8337 ctxt->ctxtType = typeDecl;
8338 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
8339 ctxt->ctxtType = ctxtType;
8340 }
8341 /* Fixup base type */
8342 if ((typeDecl->baseType != NULL) &&
8343 (typeDecl->baseType->contentType ==
8344 XML_SCHEMA_CONTENT_UNKNOWN)) {
8345 /* OPTIMIZE: Actually this one will never by hit, since
8346 * the base type is already type-fixed in <restriction>.
8347 */
8348 ctxtType = ctxt->ctxtType;
8349 ctxt->ctxtType = typeDecl;
8350 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
8351 ctxt->ctxtType = ctxtType;
8352 }
8353 /* Base type:
8354 * 2 If the <list> or <union> alternative is chosen,
8355 * then the ·simple ur-type definition·.
8356 */
8357 if (typeDecl->subtypes->type ==
8358 XML_SCHEMA_TYPE_LIST) {
8359 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8360 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
8361 } else if (typeDecl->subtypes->type ==
8362 XML_SCHEMA_TYPE_UNION) {
8363 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8364 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8365 } else if (typeDecl->subtypes->type ==
8366 XML_SCHEMA_TYPE_RESTRICTION) {
8367 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
8368
8369 /*
8370 * Variety
8371 * If the <restriction> alternative is chosen, then the
8372 * {variety} of the {base type definition}.
8373 */
8374 if (typeDecl->baseType != NULL) {
8375 if (typeDecl->baseType->flags &
8376 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
8377 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
8378 else if (typeDecl->baseType->flags &
8379 XML_SCHEMAS_TYPE_VARIETY_LIST)
8380 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
8381 else if (typeDecl->baseType->flags &
8382 XML_SCHEMAS_TYPE_VARIETY_UNION)
8383 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8384 /*
8385 * Schema Component Constraint: Simple Type Restriction
8386 * (Facets)
8387 * NOTE: Satisfaction of 1 and 2 arise from the fixup
8388 * applied beforehand.
8389 *
8390 * 3 The {facets} of R are the union of S and the {facets}
8391 * of B, eliminating duplicates. To eliminate duplicates,
8392 * when a facet of the same kind occurs in both S and the
8393 * {facets} of B, the one in the {facets} of B is not
8394 * included, with the exception of enumeration and pattern
8395 * facets, for which multiple occurrences with distinct values
8396 * are allowed.
8397 */
8398 if (typeDecl->baseType->facetSet != NULL) {
8399 last = typeDecl->facetSet;
8400 if (last != NULL)
8401 while (last->next != NULL)
8402 last = last->next;
8403 cur = typeDecl->baseType->facetSet;
8404 for (; cur != NULL; cur = cur->next) {
8405 /*
8406 * Base patterns won't be add here:
8407 * they are ORed in a type and
8408 * ANDed in derived types. This will
8409 * happed at validation level by
8410 * walking the base axis of the type.
8411 */
8412 if (cur->facet->type ==
8413 XML_SCHEMA_FACET_PATTERN)
8414 continue;
8415 facet = NULL;
8416 if ((typeDecl->facetSet != NULL) &&
8417 (cur->facet->type !=
8418 XML_SCHEMA_FACET_PATTERN) &&
8419 (cur->facet->type !=
8420 XML_SCHEMA_FACET_ENUMERATION)) {
8421 facet = typeDecl->facetSet;
8422 do {
8423 if (cur->facet->type ==
8424 facet->facet->type)
8425 break;
8426 facet = facet->next;
8427 } while (facet != NULL);
8428 }
8429 if (facet == NULL) {
8430 facet = (xmlSchemaFacetLinkPtr)
8431 xmlMalloc(sizeof(xmlSchemaFacetLink));
8432 if (facet == NULL) {
8433 xmlSchemaPErrMemory(ctxt,
8434 "fixing simpleType", NULL);
8435 return;
8436 }
8437 facet->facet = cur->facet;
8438 facet->next = NULL;
8439 if (last == NULL)
8440 typeDecl->facetSet = facet;
8441 else
8442 last->next = facet;
8443 last = facet;
8444 }
8445 }
8446 }
8447 }
8448 }
8449 /*
8450 * Check constraints.
8451 */
8452 xmlSchemaCheckSRCSimpleType(ctxt, typeDecl);
8453 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008454 case XML_SCHEMA_TYPE_SEQUENCE:
8455 case XML_SCHEMA_TYPE_GROUP:
8456 case XML_SCHEMA_TYPE_ALL:
8457 case XML_SCHEMA_TYPE_CHOICE:
8458 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
8459 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008460 case XML_SCHEMA_TYPE_LIST:
Daniel Veillard3646d642004-06-02 19:19:14 +00008461 xmlSchemaParseListRefFixup(typeDecl, ctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008462 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
8463 break;
8464 case XML_SCHEMA_TYPE_UNION:
8465 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
8466 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
8467 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008468 case XML_SCHEMA_TYPE_BASIC:
8469 case XML_SCHEMA_TYPE_ANY:
8470 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008471 case XML_SCHEMA_TYPE_UR:
8472 case XML_SCHEMA_TYPE_ELEMENT:
8473 case XML_SCHEMA_TYPE_ATTRIBUTE:
8474 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +00008475 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008476 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008477 case XML_SCHEMA_FACET_MININCLUSIVE:
8478 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8479 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8480 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8481 case XML_SCHEMA_FACET_TOTALDIGITS:
8482 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8483 case XML_SCHEMA_FACET_PATTERN:
8484 case XML_SCHEMA_FACET_ENUMERATION:
8485 case XML_SCHEMA_FACET_WHITESPACE:
8486 case XML_SCHEMA_FACET_LENGTH:
8487 case XML_SCHEMA_FACET_MAXLENGTH:
8488 case XML_SCHEMA_FACET_MINLENGTH:
8489 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008490 if (typeDecl->subtypes != NULL)
8491 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008492 break;
8493 }
8494 }
Daniel Veillard8651f532002-04-17 09:06:27 +00008495#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008496 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008497 xmlGenericError(xmlGenericErrorContext,
8498 "Type of %s : %s:%d :", name,
8499 typeDecl->node->doc->URL,
8500 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008501 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008502 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008503 }
Daniel Veillard8651f532002-04-17 09:06:27 +00008504 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008505 case XML_SCHEMA_CONTENT_SIMPLE:
8506 xmlGenericError(xmlGenericErrorContext, "simple\n");
8507 break;
8508 case XML_SCHEMA_CONTENT_ELEMENTS:
8509 xmlGenericError(xmlGenericErrorContext, "elements\n");
8510 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00008511 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008512 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
8513 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00008514 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008515 xmlGenericError(xmlGenericErrorContext, "empty\n");
8516 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00008517 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008518 xmlGenericError(xmlGenericErrorContext, "mixed\n");
8519 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008520 /* Removed, since not used. */
8521 /*
Daniel Veillard8651f532002-04-17 09:06:27 +00008522 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008523 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
8524 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008525 */
Daniel Veillard8651f532002-04-17 09:06:27 +00008526 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008527 xmlGenericError(xmlGenericErrorContext, "basic\n");
8528 break;
8529 default:
8530 xmlGenericError(xmlGenericErrorContext,
8531 "not registered !!!\n");
8532 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00008533 }
8534#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00008535}
8536
8537/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008538 * xmlSchemaCheckFacet:
8539 * @facet: the facet
8540 * @typeDecl: the schema type definition
8541 * @ctxt: the schema parser context or NULL
8542 * @name: name of the type
8543 *
8544 * Checks the default values types, especially for facets
8545 *
8546 * Returns 0 if okay or -1 in cae of error
8547 */
8548int
8549xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008550 xmlSchemaTypePtr typeDecl,
8551 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008552{
8553 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
8554 int ret = 0;
8555
8556 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008557 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +00008558 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008559 }
8560 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008561 case XML_SCHEMA_FACET_MININCLUSIVE:
8562 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8563 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8564 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
8565 /*
8566 * Okay we need to validate the value
8567 * at that point.
8568 */
8569 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008570 xmlSchemaTypePtr base;
8571
8572 /*
8573 * TODO: Try to avoid creating a new context.
8574 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008575 vctxt = xmlSchemaNewValidCtxt(NULL);
8576 if (vctxt == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +00008577 break;
8578 /* xmlSchemaValidateSimpleValue(vctxt, typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008579 facet->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008580 */
8581 /* The value ·must· be in the
8582 * ·value space· of the ·base type·.
8583 */
8584 base = typeDecl->baseType;
8585 if (base == NULL) {
8586 xmlSchemaPErr(ctxt, typeDecl->node,
8587 XML_SCHEMAS_ERR_INTERNAL,
8588 "Internal error: xmlSchemaCheckFacet, "
8589 "the type \"%s\" has no base type.\n",
8590 typeDecl->name, NULL);
8591 return (-1);
8592 }
8593 vctxt->type = base;
8594 xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008595 facet->val = vctxt->value;
8596 vctxt->value = NULL;
8597 if (facet->val == NULL) {
8598 /* error code */
8599 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008600 xmlSchemaPErrExt(ctxt, facet->node,
8601 XML_SCHEMAP_INVALID_FACET,
8602 NULL, NULL, NULL,
8603 "Type \"%s\": the value \"%s\" of the "
8604 "facet \"%s\" is invalid.\n",
8605 name, facet->value,
8606 xmlSchemaFacetTypeToString(facet->type),
8607 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008608 }
8609 ret = -1;
8610 }
8611 xmlSchemaFreeValidCtxt(vctxt);
8612 break;
8613 }
8614 case XML_SCHEMA_FACET_ENUMERATION:{
8615 /*
8616 * Okay we need to validate the value
8617 * at that point.
8618 */
8619 xmlSchemaValidCtxtPtr vctxt;
8620 int tmp;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008621 xmlSchemaTypePtr base;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008622
Daniel Veillard01fa6152004-06-29 17:04:39 +00008623 /* 4.3.5.5 Constraints on enumeration Schema Components
8624 * Schema Component Constraint: enumeration valid restriction
8625 * It is an ·error· if any member of {value} is not in the
8626 * ·value space· of {base type definition}.
8627 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008628 vctxt = xmlSchemaNewValidCtxt(NULL);
8629 if (vctxt == NULL)
8630 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008631 base = typeDecl->baseType;
8632 if (base == NULL) {
8633 xmlSchemaPErr(ctxt, typeDecl->node,
8634 XML_SCHEMAS_ERR_INTERNAL,
8635 "Internal error: xmlSchemaCheckFacet, "
8636 "the type \"%s\" has no base type.\n",
8637 typeDecl->name, NULL);
8638 return (-1);
8639 }
8640 vctxt->type = base;
8641 tmp = xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1);
8642 /* tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008643 facet->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008644 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008645 if (tmp != 0) {
8646 if (ctxt != NULL) {
8647 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008648 XML_SCHEMAP_INVALID_ENUM,
8649 "Type \"%s\": the value \"%s\" of the "
8650 "facet \"enumeration\" is invalid.\n",
8651 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008652 }
8653 ret = -1;
8654 }
8655 xmlSchemaFreeValidCtxt(vctxt);
8656 break;
8657 }
8658 case XML_SCHEMA_FACET_PATTERN:
8659 facet->regexp = xmlRegexpCompile(facet->value);
8660 if (facet->regexp == NULL) {
8661 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008662 XML_SCHEMAP_REGEXP_INVALID,
8663 "Type \"%s\": the value \"%s\" of the "
8664 "facet \"pattern\" is invalid.\n",
8665 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008666 ret = -1;
8667 }
8668 break;
8669 case XML_SCHEMA_FACET_TOTALDIGITS:
8670 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8671 case XML_SCHEMA_FACET_LENGTH:
8672 case XML_SCHEMA_FACET_MAXLENGTH:
8673 case XML_SCHEMA_FACET_MINLENGTH:{
8674 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008675
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008676 tmp =
8677 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
8678 facet->value,
8679 &facet->val);
8680 if (tmp != 0) {
8681 /* error code */
8682 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008683 xmlSchemaPErrExt(ctxt, facet->node,
8684 XML_SCHEMAP_INVALID_FACET_VALUE,
8685 NULL, NULL, NULL,
8686 "Type \"%s\": the value \"%s\" of the "
8687 "facet \"%s\" is invalid.\n",
8688 name, facet->value,
8689 xmlSchemaFacetTypeToString(facet->type),
8690 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008691 }
8692 ret = -1;
8693 }
8694 break;
8695 }
8696 case XML_SCHEMA_FACET_WHITESPACE:{
8697 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
8698 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
8699 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
8700 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
8701 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
8702 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
8703 } else {
8704 if (ctxt != NULL) {
8705 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008706 XML_SCHEMAP_INVALID_WHITE_SPACE,
8707 "Type \"%s\": the value \"%s\" of the "
8708 "facet \"whiteSpace\" is invalid.\n",
8709 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008710 }
8711 ret = -1;
8712 }
8713 }
8714 default:
8715 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008716 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008717 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008718}
8719
8720/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008721 * xmlSchemaCheckDefaults:
8722 * @typeDecl: the schema type definition
8723 * @ctxt: the schema parser context
8724 *
8725 * Checks the default values types, especially for facets
8726 */
8727static void
8728xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008729 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00008730{
Daniel Veillard4255d502002-04-16 15:50:10 +00008731 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +00008732 name = typeDecl->name;
8733 /*
8734 * NOTE: It is intended to use the facets list, instead
8735 * of facetSet.
8736 */
8737 if (typeDecl->facets != NULL) {
8738 xmlSchemaFacetPtr facet = typeDecl->facets;
8739
8740 while (facet != NULL) {
8741 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
8742 facet = facet->next;
8743 }
8744 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008745}
8746
8747/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00008748 * xmlSchemaAttrGrpFixup:
8749 * @attrgrpDecl: the schema attribute definition
8750 * @ctxt: the schema parser context
8751 * @name: the attribute name
8752 *
8753 * Fixes finish doing the computations on the attributes definitions
8754 */
8755static void
Daniel Veillard3646d642004-06-02 19:19:14 +00008756xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008757 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00008758{
8759 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00008760 name = attrgrp->name;
8761 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008762 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00008763 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008764 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00008765
Daniel Veillard3646d642004-06-02 19:19:14 +00008766 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref, attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008767 if (ref == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008768 xmlSchemaPErr(ctxt, attrgrp->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008769 XML_SCHEMAP_SRC_RESOLVE,
8770 "Attribute group \"%s\": the QName \"%s\" of the attribute "
8771 "\"ref\" does not resolve to a schema "
8772 "component.\n",
8773 name, attrgrp->ref);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008774 return;
8775 }
8776 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00008777 attrgrp->attributes = ref->attributes;
8778 attrgrp->attributeWildcard = ref->attributeWildcard;
8779 }
8780 /*
8781 * Removed, since a global attribute group does not need to hold any
8782 * attributes or wildcard
8783 */
8784 /*
8785 else {
8786 xmlSchemaPErr(ctxt, attrgrp->node, XML_SCHEMAP_NOATTR_NOREF,
8787 "Schemas: attribute group %s has no attributes nor reference\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008788 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00008789 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008790 */
Daniel Veillard13e04c62002-04-23 17:51:29 +00008791}
8792
8793/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008794 * xmlSchemaAttrFixup:
8795 * @attrDecl: the schema attribute definition
8796 * @ctxt: the schema parser context
8797 * @name: the attribute name
8798 *
8799 * Fixes finish doing the computations on the attributes definitions
8800 */
8801static void
8802xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008803 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00008804{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008805 /*
8806 * The simple type definition corresponding to the <simpleType> element
8807 * information item in the [children], if present, otherwise the simple
8808 * type definition ·resolved· to by the ·actual value· of the type
8809 * [attribute], if present, otherwise the ·simple ur-type definition·.
8810 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008811 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008812 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008813 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008814 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008815 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008816 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008817
Daniel Veillard01fa6152004-06-29 17:04:39 +00008818 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
8819 attrDecl->typeNs);
8820 if (type == NULL) {
8821 xmlSchemaPErr(ctxt, attrDecl->node,
8822 XML_SCHEMAP_SRC_RESOLVE,
8823 "Attribute \"%s\": the QName \"%s\" of the attribute "
8824 "\"type\" does not resolve to a schema "
8825 "component.\n",
8826 name, attrDecl->typeName);
8827 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008828 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008829 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008830 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00008831
Daniel Veillard3646d642004-06-02 19:19:14 +00008832 ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008833 if (ref == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008834 xmlSchemaPErr(ctxt, attrDecl->node,
8835 XML_SCHEMAP_SRC_RESOLVE,
8836 "Attribute \"%s\": the QName \"%s\" of the attribute "
8837 "\"ref\" does not resolve to a schema "
8838 "component.\n",
8839 name, attrDecl->ref);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008840 return;
8841 }
8842 xmlSchemaAttrFixup(ref, ctxt, NULL);
8843 attrDecl->subtypes = ref->subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +00008844 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008845 attrDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
Daniel Veillard4255d502002-04-16 15:50:10 +00008846 }
8847}
8848
8849/**
8850 * xmlSchemaParse:
8851 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00008852 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00008853 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00008854 * XML Shema struture which can be used to validate instances.
8855 * *WARNING* this interface is highly subject to change
8856 *
8857 * Returns the internal XML Schema structure built from the resource or
8858 * NULL in case of error
8859 */
8860xmlSchemaPtr
8861xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
8862{
8863 xmlSchemaPtr ret = NULL;
8864 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008865 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008866 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008867 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008868
8869 xmlSchemaInitTypes();
8870
Daniel Veillard6045c902002-10-09 21:13:59 +00008871 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00008872 return (NULL);
8873
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008874 nberrors = ctxt->nberrors;
8875 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008876 ctxt->counter = 0;
8877 ctxt->container = NULL;
8878
8879 /*
8880 * First step is to parse the input document into an DOM/Infoset
8881 */
Daniel Veillard6045c902002-10-09 21:13:59 +00008882 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008883 doc = xmlReadFile((const char *) ctxt->URL, NULL,
8884 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008885 if (doc == NULL) {
8886 xmlSchemaPErr(ctxt, NULL,
8887 XML_SCHEMAP_FAILED_LOAD,
8888 "xmlSchemaParse: could not load %s\n",
8889 ctxt->URL, NULL);
8890 return (NULL);
8891 }
Daniel Veillard6045c902002-10-09 21:13:59 +00008892 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008893 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
8894 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008895 if (doc == NULL) {
8896 xmlSchemaPErr(ctxt, NULL,
8897 XML_SCHEMAP_FAILED_PARSE,
8898 "xmlSchemaParse: could not parse\n",
8899 NULL, NULL);
8900 return (NULL);
8901 }
8902 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00008903 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00008904 } else if (ctxt->doc != NULL) {
8905 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008906 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00008907 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008908 xmlSchemaPErr(ctxt, NULL,
8909 XML_SCHEMAP_NOTHING_TO_PARSE,
8910 "xmlSchemaParse: could not parse\n",
8911 NULL, NULL);
8912 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008913 }
8914
8915 /*
8916 * Then extract the root and Schema parse it
8917 */
8918 root = xmlDocGetRootElement(doc);
8919 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008920 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8921 XML_SCHEMAP_NOROOT,
8922 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00008923 if (!preserve) {
8924 xmlFreeDoc(doc);
8925 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008926 return (NULL);
8927 }
8928
8929 /*
8930 * Remove all the blank text nodes
8931 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008932 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00008933
8934 /*
8935 * Then do the parsing for good
8936 */
8937 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00008938 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00008939 if (!preserve) {
8940 xmlFreeDoc(doc);
8941 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008942 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00008943 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008944 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008945 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00008946
8947 /*
8948 * Then fix all the references.
8949 */
8950 ctxt->schema = ret;
8951 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008952 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008953
8954 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00008955 * Then fixup all attributes declarations
8956 */
8957 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
8958
8959 /*
8960 * Then fixup all attributes group declarations
8961 */
8962 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
8963 ctxt);
8964
8965 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00008966 * Then fixup all types properties
8967 */
8968 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
8969
8970 /*
8971 * Then build the content model for all elements
8972 */
8973 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008974 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008975
8976 /*
8977 * Then check the defaults part of the type like facets values
8978 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008979 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
8980 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008981
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008982 if (ctxt->nberrors != 0) {
8983 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008984 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008985 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008986 return (ret);
8987}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008988
Daniel Veillard4255d502002-04-16 15:50:10 +00008989/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00008990 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00008991 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00008992 * @err: the error callback
8993 * @warn: the warning callback
8994 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00008995 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00008996 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00008997 */
8998void
8999xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009000 xmlSchemaValidityErrorFunc err,
9001 xmlSchemaValidityWarningFunc warn, void *ctx)
9002{
Daniel Veillard4255d502002-04-16 15:50:10 +00009003 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009004 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009005 ctxt->error = err;
9006 ctxt->warning = warn;
9007 ctxt->userData = ctx;
9008}
9009
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009010/**
9011 * xmlSchemaFacetTypeToString:
9012 * @type: the facet type
9013 *
9014 * Convert the xmlSchemaTypeType to a char string.
9015 *
9016 * Returns the char string representation of the facet type if the
9017 * type is a facet and an "Internal Error" string otherwise.
9018 */
9019static const char *
9020xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
9021{
9022 switch (type) {
9023 case XML_SCHEMA_FACET_PATTERN:
9024 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009025 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009026 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009027 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009028 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009029 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009030 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009031 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009032 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009033 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009034 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009035 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009036 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009037 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009038 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009039 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009040 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009041 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009042 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009043 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009044 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009045 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009046 return ("fractionDigits");
9047 default:
9048 break;
9049 }
9050 return ("Internal Error");
9051}
9052
9053/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00009054 * xmlSchemaValidateFacetsInternal:
9055 * @ctxt: a schema validation context
9056 * @base: the base type
9057 * @facets: the list of facets to check
9058 * @value: the lexical repr of the value to validate
9059 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +00009060 * @fireErrors: if 0, only internal errors will be fired;
9061 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00009062 *
9063 * Check a value against all facet conditions
9064 *
9065 * Returns 0 if the element is schemas valid, a positive error code
9066 * number otherwise and -1 in case of internal or API error.
9067 */
9068static int
9069xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
9070 xmlSchemaTypePtr base,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009071 xmlSchemaFacetLinkPtr facets,
William M. Bracke7091952004-05-11 15:09:58 +00009072 const xmlChar * value, int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00009073{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009074 int ret = 0;
9075 int tmp = 0;
9076 xmlSchemaTypeType type;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009077 xmlSchemaFacetLinkPtr facetLink = facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009078
Daniel Veillard01fa6152004-06-29 17:04:39 +00009079 while (facetLink != NULL) {
9080 type = facetLink->facet->type;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009081 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009082 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009083
Daniel Veillard01fa6152004-06-29 17:04:39 +00009084 while (facetLink != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009085 tmp =
Daniel Veillard01fa6152004-06-29 17:04:39 +00009086 xmlSchemaValidateFacet(base, facetLink->facet, value,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009087 ctxt->value);
9088 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009089 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009090 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009091 facetLink = facetLink->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009092 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009093 } else
Daniel Veillard01fa6152004-06-29 17:04:39 +00009094 tmp = xmlSchemaValidateFacet(base, facetLink->facet, value,
9095 ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009096
9097 if (tmp != 0) {
9098 ret = tmp;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009099 if (fireErrors) {
9100 xmlSchemaVErr(ctxt, ctxt->cur, tmp,
9101 "The value failed to validate against the facet \"%s\".\n",
9102 (const xmlChar *) xmlSchemaFacetTypeToString(type),
9103 NULL);
9104
9105 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009106 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009107 if (facetLink != NULL)
9108 facetLink = facetLink->next;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009109 }
9110 return (ret);
9111}
9112
William M. Brack87640d52004-04-17 14:58:15 +00009113/**
9114 * xmlSchemaValidateFacets:
9115 * @ctxt: a schema validation context
9116 * @base: the base type
9117 * @facets: the list of facets to check
9118 * @value: the lexical repr of the value to validate
9119 * @val: the precomputed value
9120 *
9121 * Check a value against all facet conditions
9122 *
9123 * Returns 0 if the element is schemas valid, a positive error code
9124 * number otherwise and -1 in case of internal or API error.
9125 */
9126static int
9127xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
9128 xmlSchemaTypePtr base,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009129 xmlSchemaFacetLinkPtr facets, const xmlChar * value)
William M. Brack87640d52004-04-17 14:58:15 +00009130{
9131 return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
9132}
9133
Daniel Veillard4255d502002-04-16 15:50:10 +00009134/************************************************************************
9135 * *
9136 * Simple type validation *
9137 * *
9138 ************************************************************************/
Daniel Veillard01fa6152004-06-29 17:04:39 +00009139#if 0 /* Not currently used. */
Daniel Veillard4255d502002-04-16 15:50:10 +00009140/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00009141 * xmlSchemaValidateSimpleValueUnion:
9142 * @ctxt: a schema validation context
9143 * @type: the type declaration
9144 * @value: the value to validate
9145 *
9146 * Validates a value against a union.
9147 *
9148 * Returns 0 if the value is valid, a positive error code
9149 * number otherwise and -1 in case of internal or API error.
9150 */
9151static int
9152xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
9153 xmlSchemaTypePtr type, const xmlChar * value)
9154{
9155 int ret = 0;
9156 const xmlChar *cur, *end, *prefix, *ncName;
9157 xmlChar *tmp;
9158 xmlSchemaTypePtr subtype;
9159 xmlNsPtr ns;
9160 int len;
9161
9162
9163 /* Process referenced memberTypes. */
9164 cur = type->ref;
9165 do {
9166 while (IS_BLANK_CH(*cur))
9167 cur++;
9168 end = cur;
9169 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9170 end++;
9171 if (end == cur)
9172 break;
9173 tmp = xmlStrndup(cur, end - cur);
9174 ncName = xmlSplitQName3(tmp, &len);
9175 if (ncName != NULL) {
9176 prefix = xmlStrndup(tmp, len);
9177 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
9178 } else {
9179 prefix = NULL;
9180 ncName = tmp;
9181 }
William M. Bracke7091952004-05-11 15:09:58 +00009182 /* We won't do additional checks here,
9183 * since they have been performed during parsing. */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009184 ns = xmlSearchNs(type->node->doc, type->node, prefix);
9185 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
9186 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
9187 if (tmp != NULL)
9188 xmlFree(tmp);
9189 if (prefix != NULL)
William M. Brack87640d52004-04-17 14:58:15 +00009190 xmlFree((void *)prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009191 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
9192 if ((ret == 0) || (ret == -1)) {
9193 return (ret);
9194 }
9195 cur = end;
9196 } while (*cur != 0);
9197
9198 if (type->subtypes != NULL) {
9199 subtype = type->subtypes;
9200 do {
9201 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
9202 if ((ret == 0) || (ret == -1)) {
9203 return (ret);
9204 }
9205 subtype = subtype->next;
9206 } while (subtype != NULL);
9207 }
9208 return (ret);
9209}
9210
9211/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009212 * xmlSchemaValidateSimpleValue:
9213 * @ctxt: a schema validation context
9214 * @type: the type declaration
9215 * @value: the value to validate
9216 *
9217 * Validate a value against a simple type
9218 *
9219 * Returns 0 if the value is valid, a positive error code
9220 * number otherwise and -1 in case of internal or API error.
9221 */
9222static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009223xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009224 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009225{
Daniel Veillard377e1a92004-04-16 16:30:05 +00009226 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
9227}
9228
9229/**
9230 * xmlSchemaValidateSimpleValue:
9231 * @ctxt: a schema validation context
9232 * @type: the type declaration
9233 * @value: the value to validate
William M. Bracke7091952004-05-11 15:09:58 +00009234 * @fireErrors: if 0, only internal errors will be fired;
9235 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00009236 *
9237 * Validate a value against a simple type
9238 *
9239 * Returns 0 if the value is valid, a positive error code
9240 * number otherwise and -1 in case of internal or API error.
9241 */
9242static int
9243xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
William M. Bracke7091952004-05-11 15:09:58 +00009244 xmlSchemaTypePtr type,
9245 const xmlChar * value,
9246 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00009247{
Daniel Veillard4255d502002-04-16 15:50:10 +00009248 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009249
Daniel Veillard4255d502002-04-16 15:50:10 +00009250 /*
9251 * First normalize the value accordingly to Schema Datatype
9252 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
William M. Bracke7091952004-05-11 15:09:58 +00009253 *
Daniel Veillard4255d502002-04-16 15:50:10 +00009254 * Then check the normalized value against the lexical space of the
9255 * type.
9256 */
9257 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009258 if (ctxt->value != NULL) {
9259 xmlSchemaFreeValue(ctxt->value);
9260 ctxt->value = NULL;
9261 }
9262 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
9263 ctxt->cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009264 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00009265 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
9266 "Failed to validate basic type %s\n",
9267 type->name, NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009268 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009269 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009270 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00009271
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009272 base = type->baseType;
9273 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00009274 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
9275 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009276 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009277 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009278 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009279
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009280 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00009281 * Do not validate facets or attributes when working on
9282 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009283 */
9284 if (ctxt->schema != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009285 xmlSchemaFacetLinkPtr facetLink;
9286
9287 if ((ret == 0) && (type->facetSet != NULL)) {
9288 facetLink = type->facetSet;
9289 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facetLink,
William M. Bracke7091952004-05-11 15:09:58 +00009290 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009291 }
9292 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009293 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009294 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00009295
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009296 base = type->subtypes;
9297 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00009298 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
9299 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009300 } else {
9301 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00009302 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009303 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009304 const xmlChar *cur, *end;
9305 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009306 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00009307
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009308 base = type->subtypes;
9309 if (base == NULL) {
9310 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
9311 "Internal: List type %s has no base type\n",
9312 type->name, NULL);
9313 return (-1);
9314 }
9315 cur = value;
9316 do {
William M. Brack76e95df2003-10-18 16:20:14 +00009317 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009318 cur++;
9319 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00009320 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009321 end++;
9322 if (end == cur)
9323 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009324 tmp = xmlStrndup(cur, end - cur);
William M. Bracke7091952004-05-11 15:09:58 +00009325 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base,
9326 tmp, fireErrors);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009327 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009328 if (ret2 != 0)
9329 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009330 cur = end;
9331 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009332 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
9333 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
9334 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00009335 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
9336 "Failed to validate type %s\n", type->name, NULL);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009337 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009338 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009339 TODO
9340 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009341 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009342}
Daniel Veillard01fa6152004-06-29 17:04:39 +00009343#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009344
9345/************************************************************************
9346 * *
9347 * DOM Validation code *
9348 * *
9349 ************************************************************************/
9350
9351static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009352 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009353static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009354 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +00009355 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00009356static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009357 xmlNodePtr elem,
9358 xmlSchemaElementPtr elemDecl,
9359 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00009360
Daniel Veillard3646d642004-06-02 19:19:14 +00009361
9362/**
9363 * xmlSchemaFreeAttrStates:
9364 * @state: a list of attribute states
9365 *
9366 * Free the given list of attribute states
9367 *
9368 */
9369static void
9370xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
9371{
9372 xmlSchemaAttrStatePtr tmp;
9373 while (state != NULL) {
9374 tmp = state;
9375 state = state->next;
9376 xmlFree(tmp);
9377 }
9378}
9379
Daniel Veillard4255d502002-04-16 15:50:10 +00009380/**
9381 * xmlSchemaRegisterAttributes:
9382 * @ctxt: a schema validation context
9383 * @attrs: a list of attributes
9384 *
9385 * Register the list of attributes as the set to be validated on that element
9386 *
9387 * Returns -1 in case of error, 0 otherwise
9388 */
9389static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009390xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
9391{
Daniel Veillard3646d642004-06-02 19:19:14 +00009392 xmlSchemaAttrStatePtr tmp;
9393
9394 ctxt->attr = NULL;
9395 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009396 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009397 if ((attrs->ns != NULL) &&
9398 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
9399 attrs = attrs->next;
9400 continue;
9401 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009402 tmp = (xmlSchemaAttrStatePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00009403 xmlMalloc(sizeof(xmlSchemaAttrState));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009404 if (tmp == NULL) {
9405 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009406 return (-1);
9407 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009408 tmp->attr = attrs;
9409 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
9410 tmp->next = NULL;
9411 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009412 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009413 else
9414 ctxt->attrTop->next = tmp;
9415 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009416 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009417 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009418 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00009419}
9420
9421/**
9422 * xmlSchemaCheckAttributes:
9423 * @ctxt: a schema validation context
9424 * @node: the node carrying it.
9425 *
9426 * Check that the registered set of attributes on the current node
9427 * has been properly validated.
9428 *
9429 * Returns 0 if validity constraints are met, 1 otherwise.
9430 */
9431static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009432xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
9433{
Daniel Veillard4255d502002-04-16 15:50:10 +00009434 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009435 xmlSchemaAttrStatePtr cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00009436
Daniel Veillard3646d642004-06-02 19:19:14 +00009437 cur = ctxt->attr;
9438 while ((cur != NULL) && (cur != ctxt->attrTop->next)) {
9439 if (cur->state != XML_SCHEMAS_ATTR_CHECKED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009440 ret = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00009441 if (cur->state == XML_SCHEMAS_ATTR_UNKNOWN)
William M. Bracke7091952004-05-11 15:09:58 +00009442 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009443 "Attribute \"%s\" is not allowed.\n",
9444 cur->attr->name, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009445 else if (cur->state == XML_SCHEMAS_ATTR_PROHIBITED)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009446 /*
9447 * TODO: This won't ever be touched so remove it.
9448 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009449 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009450 "Attribute \"%s\" is prohibited.\n",
9451 cur->attr->name, NULL);
9452 else if (cur->state == XML_SCHEMAS_ATTR_INVALID_VALUE) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009453 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRINVALID,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009454 "Attribute \"%s\": the value is not valid.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009455 cur->attr->name, node->name);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009456 } else if (cur->state == XML_SCHEMAS_ATTR_MISSING) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009457 if (cur->decl->ref != NULL)
9458 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009459 "Attribute \"%s\" is required but missing.\n",
9460 cur->decl->ref, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009461 else
9462 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009463 "Attribute \"%s\" is required but missing.\n",
9464 cur->decl->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009465 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009466 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009467 cur = cur->next;
9468 }
9469
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009470 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009471}
9472
William M. Brack29aa7722004-05-12 00:27:56 +00009473#if 0 /* Not currently used - remove if ever needed */
Daniel Veillard4255d502002-04-16 15:50:10 +00009474/**
9475 * xmlSchemaValidateSimpleContent:
9476 * @ctxt: a schema validation context
9477 * @elem: an element
9478 * @type: the type declaration
9479 *
9480 * Validate the content of an element expected to be a simple type
9481 *
9482 * Returns 0 if the element is schemas valid, a positive error code
9483 * number otherwise and -1 in case of internal or API error.
9484 */
9485static int
9486xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009487 xmlNodePtr node ATTRIBUTE_UNUSED)
9488{
Daniel Veillard4255d502002-04-16 15:50:10 +00009489 xmlNodePtr child;
9490 xmlSchemaTypePtr type, base;
9491 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009492 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009493
9494 child = ctxt->node;
9495 type = ctxt->type;
9496
9497 /*
9498 * Validation Rule: Element Locally Valid (Type): 3.1.3
9499 */
9500 value = xmlNodeGetContent(child);
9501 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
9502 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009503 case XML_SCHEMA_TYPE_RESTRICTION:{
9504 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00009505
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009506 base = type->baseType;
9507 if (base != NULL) {
9508 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
9509 } else {
9510 TODO}
9511 if (ret == 0) {
9512 facet = type->facets;
9513 ret =
9514 xmlSchemaValidateFacets(ctxt, base, facet, value);
9515 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009516 /*
9517 * This should attempt to validate the attributes even
9518 * when validation of the value failed.
9519 */
9520 /*
9521 if (type->attributes != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00009522 ret = xmlSchemaValidateAttributes(ctxt, node,
9523 type->attributes);
9524 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009525 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009526 break;
9527 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009528 case XML_SCHEMA_TYPE_EXTENSION:{
9529 TODO
9530 break;
9531 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009532 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009533 TODO
9534 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009535 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009536 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00009537
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009538 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009539}
William M. Brack29aa7722004-05-12 00:27:56 +00009540#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009541
9542/**
9543 * xmlSchemaValidateCheckNodeList
9544 * @nodelist: the list of nodes
9545 *
9546 * Check the node list is only made of text nodes and entities pointing
9547 * to text nodes
9548 *
9549 * Returns 1 if true, 0 if false and -1 in case of error
9550 */
9551static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009552xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
9553{
Daniel Veillard4255d502002-04-16 15:50:10 +00009554 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009555 if (nodelist->type == XML_ENTITY_REF_NODE) {
9556 TODO /* implement recursion in the entity content */
9557 }
9558 if ((nodelist->type != XML_TEXT_NODE) &&
9559 (nodelist->type != XML_COMMENT_NODE) &&
9560 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +00009561 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009562 return (0);
9563 }
9564 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009565 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009566 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009567}
9568
9569/**
9570 * xmlSchemaSkipIgnored:
9571 * @ctxt: a schema validation context
9572 * @type: the current type context
9573 * @node: the top node.
9574 *
9575 * Skip ignorable nodes in that context
9576 *
9577 * Returns the new sibling
9578 * number otherwise and -1 in case of internal or API error.
9579 */
9580static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00009581xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009582 xmlSchemaTypePtr type, xmlNodePtr node)
9583{
Daniel Veillard4255d502002-04-16 15:50:10 +00009584 /*
9585 * TODO complete and handle entities
9586 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009587 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009588 ((node->type == XML_COMMENT_NODE) ||
Daniel Veillard01fa6152004-06-29 17:04:39 +00009589 ((type->contentType == XML_SCHEMA_CONTENT_MIXED) &&
9590 (node->type == XML_TEXT_NODE)) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009591 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
9592 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
9593 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009594 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009595 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009596}
9597
9598/**
9599 * xmlSchemaValidateCallback:
9600 * @ctxt: a schema validation context
9601 * @name: the name of the element detected (might be NULL)
9602 * @type: the type
9603 *
9604 * A transition has been made in the automata associated to an element
9605 * content model
9606 */
9607static void
9608xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009609 const xmlChar * name ATTRIBUTE_UNUSED,
9610 xmlSchemaTypePtr type, xmlNodePtr node)
9611{
Daniel Veillard4255d502002-04-16 15:50:10 +00009612 xmlSchemaTypePtr oldtype = ctxt->type;
9613 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009614
Daniel Veillard4255d502002-04-16 15:50:10 +00009615#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00009616 xmlGenericError(xmlGenericErrorContext,
9617 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009618 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00009619#endif
9620 ctxt->type = type;
9621 ctxt->node = node;
9622 xmlSchemaValidateContent(ctxt, node);
9623 ctxt->type = oldtype;
9624 ctxt->node = oldnode;
9625}
9626
9627
9628#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009629
Daniel Veillard4255d502002-04-16 15:50:10 +00009630/**
9631 * xmlSchemaValidateSimpleRestrictionType:
9632 * @ctxt: a schema validation context
9633 * @node: the top node.
9634 *
9635 * Validate the content of a restriction type.
9636 *
9637 * Returns 0 if the element is schemas valid, a positive error code
9638 * number otherwise and -1 in case of internal or API error.
9639 */
9640static int
9641xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
9642 xmlNodePtr node)
9643{
9644 xmlNodePtr child;
9645 xmlSchemaTypePtr type;
9646 int ret;
9647
9648 child = ctxt->node;
9649 type = ctxt->type;
9650
9651 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00009652 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9653 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
9654 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009655 return (-1);
9656 }
9657 /*
9658 * Only text and text based entities references shall be found there
9659 */
9660 ret = xmlSchemaValidateCheckNodeList(child);
9661 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00009662 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009663 "Internal error: xmlSchemaValidateSimpleRestrictionType %s content\n",
William M. Bracke7091952004-05-11 15:09:58 +00009664 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009665 return (-1);
9666 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00009667 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
9668 "Element %s content is not a simple type\n",
9669 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009670 return (-1);
9671 }
9672 ctxt->type = type->subtypes;
9673 xmlSchemaValidateContent(ctxt, node);
9674 ctxt->type = type;
9675 return (ret);
9676}
9677#endif
9678
Daniel Veillard01fa6152004-06-29 17:04:39 +00009679#if 0 /* Not used any more */
Daniel Veillard4255d502002-04-16 15:50:10 +00009680/**
9681 * xmlSchemaValidateSimpleType:
9682 * @ctxt: a schema validation context
9683 * @node: the top node.
9684 *
9685 * Validate the content of an simple type.
9686 *
9687 * Returns 0 if the element is schemas valid, a positive error code
9688 * number otherwise and -1 in case of internal or API error.
9689 */
9690static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009691xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
9692{
Daniel Veillard4255d502002-04-16 15:50:10 +00009693 xmlNodePtr child;
William M. Bracke7091952004-05-11 15:09:58 +00009694 xmlSchemaTypePtr type, base, variety;
Daniel Veillard4255d502002-04-16 15:50:10 +00009695 xmlAttrPtr attr;
9696 int ret;
William M. Bracke7091952004-05-11 15:09:58 +00009697 xmlChar *value;
9698
Daniel Veillard4255d502002-04-16 15:50:10 +00009699
9700 child = ctxt->node;
9701 type = ctxt->type;
9702
9703 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00009704 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9705 "Internal error: xmlSchemaValidateSimpleType %s\n",
9706 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009707 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009708 }
9709 /*
9710 * Only text and text based entities references shall be found there
9711 */
9712 ret = xmlSchemaValidateCheckNodeList(child);
9713 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00009714 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9715 "Internal error: xmlSchemaValidateSimpleType %s content\n",
9716 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009717 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009718 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00009719 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
9720 "Element %s content is not a simple type\n",
9721 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009722 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009723 }
9724 /*
9725 * Validation Rule: Element Locally Valid (Type): 3.1.1
William M. Bracke7091952004-05-11 15:09:58 +00009726 */
9727
Daniel Veillard4255d502002-04-16 15:50:10 +00009728 attr = node->properties;
9729 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009730 if ((attr->ns == NULL) ||
9731 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
9732 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
9733 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
9734 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
9735 (!xmlStrEqual
9736 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
William M. Bracke7091952004-05-11 15:09:58 +00009737 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
9738 "Element %s: attribute %s should not be present\n",
9739 node->name, attr->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009740 return (ctxt->err);
9741 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009742 }
William M. Bracke7091952004-05-11 15:09:58 +00009743 /* TODO:
9744 * If {variety} is ·atomic· then the {variety} of {base type definition}
9745 * must be ·atomic·.
9746 * If {variety} is ·list· then the {variety} of {item type definition}
9747 * must be either ·atomic· or ·union·.
9748 * If {variety} is ·union· then {member type definitions} must be a list
9749 * of datatype definitions.
9750 */
9751 if (type->subtypes == NULL) {
9752 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9753 "Internal error: xmlSchemaValidateSimpleType; "
9754 "simple type %s does not define a variety\n",
9755 node->name, NULL);
9756 return (ctxt->err);
9757 }
9758 /* Varieties: Restriction or List or Union. */
9759 variety = type->subtypes;
9760 ctxt->type = variety;
9761 value = xmlNodeGetContent(child);
9762 switch (variety->type) {
9763 case XML_SCHEMA_TYPE_RESTRICTION:{
William M. Bracke7091952004-05-11 15:09:58 +00009764 base = variety->baseType;
9765 if (base != NULL) {
9766 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
9767 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009768 TODO}
9769
Daniel Veillard3646d642004-06-02 19:19:14 +00009770 /* Removed due to changes of attribute validation:
William M. Bracke7091952004-05-11 15:09:58 +00009771 if ((ret == 0) && (variety->attributes != NULL)) {
9772 ret = xmlSchemaValidateAttributes(ctxt, node,
9773 variety->attributes);
9774 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009775 */
William M. Bracke7091952004-05-11 15:09:58 +00009776 break;
9777 }
9778 case XML_SCHEMA_TYPE_LIST:
9779 case XML_SCHEMA_TYPE_UNION: {
9780 ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
9781 break;
9782 }
9783 default:{
9784 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9785 "Internal error: xmlSchemaValidateSimpleType; "
9786 "simple type %s defines unknown content: %s\n",
9787 variety->name, NULL);
9788 ret = ctxt->err;
9789 }
9790 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009791 if ((ret == 0) && (variety->facetSet != NULL)) {
9792 ret = xmlSchemaValidateFacets(ctxt, base, variety->facetSet, value);
9793 }
William M. Bracke7091952004-05-11 15:09:58 +00009794 if (value != NULL)
9795 xmlFree(value);
9796
9797 /* This was removed, since a simple content is not a content of a
9798 * simple type, but of a complex type.
9799 * ret = xmlSchemaValidateSimpleContent(ctxt, node);
9800 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009801 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009802 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009803}
Daniel Veillard01fa6152004-06-29 17:04:39 +00009804#endif
9805
9806/**
9807 * xmlSchemaValidateSimpleTypeValue:
9808 * @ctxt: a schema validation context
9809 * @value: the value to be validated
9810 * @fireErrors: shall errors be reported?
9811 * @applyFacets: shall facets be applied?
9812 *
9813 * Validates a value by the given type (user derived or built-in).
9814 *
9815 * Returns 0 if the value is valid, a positive error code
9816 * number otherwise and -1 in case of an internal or API error.
9817 * Note on reported errors: Although it might be nice to report
9818 * the name of the simple/complex type, used to validate the content
9819 * of a node, it is quite unnecessary: for global defined types
9820 * the local name of the element is equal to the NCName of the type,
9821 * for local defined types it makes no sense to output the internal
9822 * computed name of the type. TODO: Instead, one should attach the
9823 * struct of the type involved to the error handler - this allows
9824 * the report of any additional information by the user.
9825 * TODO: Correct character normalization of union simple types.
9826 */
9827static int
9828xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
9829 const xmlChar *value,
9830 int fireErrors,
9831 int applyFacets)
9832{
9833 xmlSchemaTypePtr type;
9834 int ret = 0;
9835 type = ctxt->type;
9836
9837 if (type->type == XML_SCHEMA_TYPE_BASIC) {
9838 xmlNodePtr child;
9839
9840 if (ctxt->value != NULL) {
9841 xmlSchemaFreeValue(ctxt->value);
9842 ctxt->value = NULL;
9843 }
9844 child = ctxt->node;
9845 while (child != NULL) {
9846 switch (child->type) {
9847 case XML_TEXT_NODE:
9848 case XML_CDATA_SECTION_NODE:
9849 case XML_PI_NODE:
9850 case XML_COMMENT_NODE:
9851 case XML_XINCLUDE_START:
9852 case XML_XINCLUDE_END:
9853 break;
9854 case XML_ENTITY_REF_NODE:
9855 case XML_ENTITY_NODE:
9856 TODO break;
9857 case XML_ELEMENT_NODE:
9858 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INVALIDELEM,
9859 "Element \"%s\": child \"%s\" should not be present.\n",
9860 ctxt->cur->name, child->name);
9861 return (ctxt->err);
9862 case XML_ATTRIBUTE_NODE:
9863 case XML_DOCUMENT_NODE:
9864 case XML_DOCUMENT_TYPE_NODE:
9865 case XML_DOCUMENT_FRAG_NODE:
9866 case XML_NOTATION_NODE:
9867 case XML_HTML_DOCUMENT_NODE:
9868 case XML_DTD_NODE:
9869 case XML_ELEMENT_DECL:
9870 case XML_ATTRIBUTE_DECL:
9871 case XML_ENTITY_DECL:
9872 case XML_NAMESPACE_DECL:
9873#ifdef LIBXML_DOCB_ENABLED
9874 case XML_DOCB_DOCUMENT_NODE:
9875#endif
9876 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INVALIDELEM,
9877 "Element \"%s\": node type of node unexpected here.\n",
9878 ctxt->cur->name, NULL);
9879 return (ctxt->err);
9880 }
9881 child = child->next;
9882 }
9883 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
9884 ctxt->cur);
9885 if (ret > 0) {
9886 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
9887 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
9888 else
9889 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
9890 if (fireErrors) {
9891 if (ctxt->cur->type == XML_ATTRIBUTE_NODE)
9892 xmlSchemaVErr(ctxt, ctxt->cur,
9893 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
9894 "The value of attribute \"%s\" is not valid.\n",
9895 ctxt->cur->name, NULL);
9896 else
9897 xmlSchemaVErr(ctxt, ctxt->cur,
9898 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
9899 "The value is not valid.\n",
9900 NULL, NULL);
9901 }
9902 } else if (ret < 0) {
9903 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9904 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9905 "validating built-in type \"%s\"\n",
9906 type->name, NULL);
9907 }
9908 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
9909 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
9910 * a literal in the ·lexical space· of {base type definition}
9911 */
9912 ctxt->type = type->baseType;
9913 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 0);
9914 if (ret < 0) {
9915 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9916 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9917 "validating atomic simple type \"%s\"\n",
9918 type->name, NULL);
9919 } else if (ret > 0) {
9920 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
9921 if (fireErrors) {
9922 xmlSchemaVErr(ctxt, ctxt->cur,
9923 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
9924 "The value is not valid.\n",
9925 NULL, NULL);
9926 }
9927
9928 } else if ((applyFacets) &&
9929 (type->facetSet != NULL)) {
9930 xmlSchemaTypePtr builtIn;
9931
9932 /*
9933 * Check facets. Be sure to pass the built-in type to
9934 * xmlSchemaValidateFacetsInternal.
9935 */
9936 builtIn = type->baseType;
9937 while (builtIn->type != XML_SCHEMA_TYPE_BASIC)
9938 builtIn = builtIn->baseType;
9939 ret = xmlSchemaValidateFacetsInternal(ctxt, builtIn,
9940 type->facetSet, value, fireErrors);
9941 if (ret < 0) {
9942 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9943 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9944 "validating facets of atomic simple type \"%s\"\n",
9945 type->name, NULL);
9946 } else if (ret > 0) {
9947 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
9948 if (fireErrors) {
9949 xmlSchemaVErr(ctxt, ctxt->cur,
9950 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
9951 "The value is not valid.\n",
9952 NULL, NULL);
9953 }
9954 }
9955 }
9956 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
9957
9958 xmlSchemaTypePtr tmpType;
9959 const xmlChar *cur, *end;
9960 xmlChar *tmp;
9961 int len = 0;
9962
9963 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
9964 * of white space separated tokens, each of which ·match·es a literal
9965 * in the ·lexical space· of {item type definition}
9966 */
9967
9968 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
9969 cur = value;
9970 do {
9971 while (IS_BLANK_CH(*cur))
9972 cur++;
9973 end = cur;
9974 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9975 end++;
9976 if (end == cur)
9977 break;
9978 tmp = xmlStrndup(cur, end - cur);
9979 len++;
9980 ctxt->type = tmpType;
9981 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmp, 0, 1);
9982 xmlFree(tmp);
9983 if (ret > 0) {
9984 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
9985 if (fireErrors) {
9986 xmlSchemaVErr(ctxt, ctxt->cur,
9987 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
9988 "The value is not valid.\n",
9989 NULL, NULL);
9990 }
9991 break;
9992 } else if (ret < 0)
9993 break;
9994 cur = end;
9995 } while (*cur != 0);
9996 /*
9997 * Check facets.
9998 */
9999 if (ret < 0) {
10000 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10001 "Internal error: xmlSchemaValidateSimpleTypeValue, "
10002 "validating list simple type \"%s\"\n",
10003 type->name, NULL);
10004 } else if ((ret == 0) && (applyFacets) &&
10005 (type->facetSet != NULL)) {
10006 int expLen, okFacet = 0, hasFacet = 0;
10007 xmlSchemaFacetPtr facet;
10008 xmlSchemaFacetLinkPtr facetLink;
10009 xmlChar *collapsedValue = NULL;
10010
10011 /*
10012 * The value of ·whiteSpace· is fixed to the value collapse.
10013 */
10014 collapsedValue = xmlSchemaCollapseString((const xmlChar *) value);
10015 if (collapsedValue != NULL)
10016 value = (const xmlChar *) collapsedValue;
10017 facetLink = type->facetSet;
10018 do {
10019 facet = facetLink->facet;
10020 /*
10021 * List types need a special facet treatment.
10022 * Skip whiteSpace, since it is fixed to "collapse".
10023 */
10024 if ((facet->type != XML_SCHEMA_FACET_WHITESPACE) &&
10025 (facet->type != XML_SCHEMA_FACET_PATTERN)) {
10026 ret = xmlSchemaValidateListSimpleTypeFacet(facet, value,
10027 len, &expLen);
10028 if (facet->type == XML_SCHEMA_FACET_ENUMERATION) {
10029 hasFacet = 1;
10030 if (ret == 0)
10031 okFacet = 1;
10032 } else if ((ret > 0) && (fireErrors)) {
10033 char l[25], fl[25];
10034 /* FIXME: What is the max expected string length of the
10035 * length value?
10036 */
10037 snprintf(l, 24, "%d", len);
10038 snprintf(fl, 24, "%d", expLen);
10039 if (ret == XML_SCHEMAV_CVC_LENGTH_VALID) {
10040 xmlSchemaVErr(ctxt, ctxt->cur, ret,
10041 "The value with length \"%s\" is not "
10042 "facet-valid with respect to length = \"%s\".\n",
10043 l, fl);
10044 } else if (ret == XML_SCHEMAV_CVC_MINLENGTH_VALID) {
10045 xmlSchemaVErr(ctxt, ctxt->cur, ret,
10046 "The value with length \"%s\" is not "
10047 "facet-valid with respect to minLength = \"%s\".\n",
10048 l, fl);
10049 } else if (ret == XML_SCHEMAV_CVC_MAXLENGTH_VALID) {
10050 xmlSchemaVErr(ctxt, ctxt->cur, ret,
10051 "The value with length \"%s\" is not "
10052 "facet-valid with respect to maxLength = \"%s\".\n",
10053 l, fl);
10054 } else {
10055 xmlSchemaVErr(ctxt, ctxt->cur, ret,
10056 "The value is not valid with respect "
10057 "to the facet \"%s\".\n",
10058 xmlSchemaFacetTypeToString(facet->type),
10059 NULL);
10060 }
10061 } else if (ret < 0) {
10062 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10063 "Internal error: xmlSchemaValidateSimpleTypeValue, "
10064 "validating facets of list simple type \"%s\"\n",
10065 type->name, NULL);
10066 break;
10067 }
10068 }
10069 facetLink = facetLink->next;
10070 } while (facetLink != NULL);
10071 if (ret >= 0) {
10072 if ((hasFacet) && (okFacet == 0)) {
10073 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
10074 if (fireErrors) {
10075 /*
10076 * TODO: Try to create a report that outputs all the enumeration
10077 * values in use.
10078 */
10079 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_CVC_ENUMERATION_VALID,
10080 "The value is not valid with respect "
10081 "to the \"enumeration\" facet(s).\n",
10082 NULL, NULL);
10083 }
10084
10085 }
10086 /*
10087 * Pattern facets are ORed at type level and ANDed
10088 * if derived. Walk the base axis.
10089 */
10090 hasFacet = 0;
10091 tmpType = type;
10092 do {
10093 okFacet = 0;
10094 for (facetLink = tmpType->facetSet; facetLink != NULL;
10095 facetLink = facetLink->next) {
10096 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
10097 continue;
10098 okFacet = xmlSchemaValidateListSimpleTypeFacet(
10099 facetLink->facet, value, len, &expLen);
10100 if (okFacet <= 0)
10101 break;
10102 }
10103 if (okFacet != 0)
10104 break;
10105 tmpType = tmpType->baseType;
10106 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
10107 if (okFacet < 0) {
10108 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10109 "Internal error: xmlSchemaValidateSimpleTypeValue, "
10110 "validating \"pattern\" facets of type \"%s\"\n",
10111 type->name, NULL);
10112 } else if (okFacet > 0) {
10113 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
10114 if (fireErrors) {
10115 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_CVC_ENUMERATION_VALID,
10116 "The value is not valid with respect "
10117 "to the \"pattern\" facet(s) of type "
10118 "\"%s\".\n",
10119 tmpType->name, NULL);
10120 }
10121 }
10122 }
10123
10124 if (collapsedValue != NULL)
10125 xmlFree(collapsedValue);
10126 }
10127 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10128 xmlSchemaTypeLinkPtr memberLink;
10129
10130 /*
10131 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
10132 * not apply directly; however, the normalization behavior of ·union·
10133 * types is controlled by the value of whiteSpace on that one of the
10134 * ·memberTypes· against which the ·union· is successfully validated.
10135 *
10136 * This means that the value is normalized by the first validating
10137 * member type, then the facets of the union type are applied. This
10138 * needs changing of the value!
10139 */
10140
10141 /*
10142 * 1.2.3 if {variety} is ·union· then the string must ·match· a
10143 * literal in the ·lexical space· of at least one member of
10144 * {member type definitions}
10145 */
10146 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
10147 if (memberLink == NULL) {
10148 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10149 "Internal error: xmlSchemaValidateSimpleTypeValue, "
10150 "union simple type \"%s\" has no member types\n",
10151 type->name, NULL);
10152 ret = -1;
10153 }
10154 if (ret == 0) {
10155 while (memberLink != NULL) {
10156 ctxt->type = memberLink->type;
10157 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1);
10158 if ((ret <= 0) || (ret == 0))
10159 break;
10160 memberLink = memberLink->next;
10161 }
10162 if (ret > 0) {
10163 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
10164 if (fireErrors) {
10165 xmlSchemaVErr(ctxt, ctxt->cur,
10166 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3,
10167 "The value is not valid.\n",
10168 NULL, NULL);
10169 }
10170 } else if (ret < 0) {
10171 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10172 "Internal error: xmlSchemaValidateSimpleTypeValue, "
10173 "validating members of union simple type \"%s\"\n",
10174 type->name, NULL);
10175 }
10176 }
10177 /*
10178 * Apply facets (pattern, enumeration).
10179 */
10180 if ((ret == 0) && (applyFacets) &&
10181 (type->facetSet != NULL)) {
10182 xmlSchemaTypePtr anySimpleType;
10183 /*
10184 * Check facets. Be sure to pass the built-in type (the
10185 * simple ur-type in this case) to xmlSchemaValidateFacetsInternal.
10186 */
10187 anySimpleType = type->baseType;
10188 while (anySimpleType->type != XML_SCHEMA_TYPE_BASIC)
10189 anySimpleType = anySimpleType->baseType;
10190 ret = xmlSchemaValidateFacetsInternal(ctxt, anySimpleType,
10191 type->facetSet, value, fireErrors);
10192 if (ret < 0) {
10193 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10194 "Internal error: xmlSchemaValidateSimpleTypeValue, "
10195 "validating facets of union simple type \"%s\"\n",
10196 type->name, NULL);
10197 } else if (ret > 0) {
10198 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
10199 if (fireErrors) {
10200 xmlSchemaVErr(ctxt, ctxt->cur,
10201 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
10202 "The value is not valid.\n",
10203 NULL, NULL);
10204 }
10205 }
10206 }
10207 }
10208 ctxt->type = type;
10209 return (ret);
10210}
10211
10212/**
10213 * xmlSchemaValidateSimpleTypeElement:
10214 * @ctxt: a schema validation context
10215 * @node: the element node to be validated.
10216 *
10217 * Validate the element against a simple type.
10218 *
10219 * Returns 0 if the element is valid, a positive error code
10220 * number otherwise and -1 in case of an internal or API error.
10221 */
10222static int
10223xmlSchemaValidateSimpleTypeElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10224{
10225 xmlNodePtr child;
10226 xmlSchemaTypePtr type;
10227 xmlAttrPtr attr;
10228 int ret;
10229 xmlChar *value;
10230
10231
10232 child = ctxt->node;
10233 type = ctxt->type;
10234
10235 if ((ctxt == NULL) || (type == NULL)) {
10236 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10237 "Internal error: xmlSchemaValidateSimpleTypeElement %s\n",
10238 node->name, NULL);
10239 return (-1);
10240 }
10241
10242 /*
10243 * Only text and text based entities references shall be found there
10244 */
10245 ret = xmlSchemaValidateCheckNodeList(child);
10246 if (ret < 0) {
10247 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10248 "Internal error: xmlSchemaValidateSimpleTypeElement %s content\n",
10249 node->name, NULL);
10250 return (-1);
10251 } else if (ret == 0) {
10252 /* 3.1.2 The element information item must have no element
10253 * information item [children].
10254 */
10255 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_TYPE_3_1_2,
10256 "Element \"%s\" must have no element children.\n",
10257 node->name, NULL);
10258 return (-1);
10259 }
10260 /*
10261 * Validation Rule: Element Locally Valid (Type): 3.1.1
10262 */
10263 attr = node->properties;
10264 while (attr != NULL) {
10265 if ((attr->ns == NULL) ||
10266 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
10267 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
10268 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
10269 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
10270 (!xmlStrEqual
10271 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
10272 xmlSchemaVErr(ctxt, node,
10273 XML_SCHEMAV_CVC_TYPE_3_1_1,
10274 "The attributes of element \"%s\" must be empty, excepting "
10275 "those whose namespace name is identical to "
10276 "http://www.w3.org/2001/XMLSchema-instance and whose local "
10277 "name is one of type, nil, schemaLocation or "
10278 "noNamespaceSchemaLocation.\n",
10279 node->name, attr->name);
10280 return (ctxt->err);
10281 }
10282 attr = attr->next;
10283 }
10284 value = xmlNodeGetContent(child);
10285 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1);
10286 if (value != NULL)
10287 xmlFree(value);
10288
10289 ctxt->type = type;
10290 return (ret);
10291}
Daniel Veillard4255d502002-04-16 15:50:10 +000010292
10293/**
10294 * xmlSchemaValidateElementType:
10295 * @ctxt: a schema validation context
10296 * @node: the top node.
10297 *
10298 * Validate the content of an element type.
10299 * Validation Rule: Element Locally Valid (Complex Type)
10300 *
10301 * Returns 0 if the element is schemas valid, a positive error code
10302 * number otherwise and -1 in case of internal or API error.
10303 */
10304static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010305xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10306{
Daniel Veillard4255d502002-04-16 15:50:10 +000010307 xmlNodePtr child;
10308 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010309 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +000010310 xmlSchemaElementPtr decl;
Daniel Veillard3646d642004-06-02 19:19:14 +000010311 int ret;
10312 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
10313
Daniel Veillard01fa6152004-06-29 17:04:39 +000010314 /* This one is called by xmlSchemaValidateContent only. */
Daniel Veillard3646d642004-06-02 19:19:14 +000010315 /*
10316 * TODO: Look into "xmlSchemaValidateElement" for missing parts, which should
10317 * go in here as well.
10318 */
10319
10320 /* TODO: Is this one called always with an element declaration as the
10321 * context's type?
10322 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010323
10324 oldregexp = ctxt->regexp;
10325
10326 child = ctxt->node;
10327 type = ctxt->type;
10328
10329 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000010330 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10331 "Internal error: xmlSchemaValidateElementType\n",
10332 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010333 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000010334 }
10335 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010336 if (type->minOccurs > 0) {
William M. Bracke7091952004-05-11 15:09:58 +000010337 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
10338 "Element %s: missing child %s\n",
10339 node->name, type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010340 }
10341 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010342 }
10343
10344 /*
10345 * Verify the element matches
10346 */
10347 if (!xmlStrEqual(child->name, type->name)) {
William M. Bracke7091952004-05-11 15:09:58 +000010348 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
10349 "Element %s: missing child %s found %s\n",
10350 node->name, type->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010351 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010352 }
10353 /*
10354 * Verify the attributes
10355 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010356
10357 attrs = ctxt->attr;
10358 attrTop = ctxt->attrTop;
10359
Daniel Veillard01fa6152004-06-29 17:04:39 +000010360 xmlSchemaRegisterAttributes(ctxt, child->properties);
Daniel Veillard3646d642004-06-02 19:19:14 +000010361
Daniel Veillard4255d502002-04-16 15:50:10 +000010362 /*
10363 * Verify the element content recursively
10364 */
10365 decl = (xmlSchemaElementPtr) type;
10366 oldregexp = ctxt->regexp;
10367 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010368 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
10369 (xmlRegExecCallbacks)
10370 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000010371#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010372 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010373#endif
10374 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010375 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
10376 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +000010377
10378 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010379 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010380#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010381 xmlGenericError(xmlGenericErrorContext,
10382 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000010383#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010384 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000010385 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
10386 "Element %s content check failed\n",
10387 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010388 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +000010389 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
10390 "Element %s content check failure\n",
10391 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010392#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010393 } else {
10394 xmlGenericError(xmlGenericErrorContext,
10395 "Element %s content check succeeded\n",
10396 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010397
10398#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010399 }
10400 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000010401 }
10402 /*
10403 * Verify that all attributes were Schemas-validated
10404 */
10405 xmlSchemaCheckAttributes(ctxt, node);
Daniel Veillard3646d642004-06-02 19:19:14 +000010406 if (ctxt->attr != NULL)
10407 xmlSchemaFreeAttributeStates(ctxt->attr);
10408 ctxt->attr = attrs;
10409 ctxt->attrTop = attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000010410 ctxt->regexp = oldregexp;
Daniel Veillard4255d502002-04-16 15:50:10 +000010411 ctxt->node = child;
10412 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010413 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010414}
10415
Daniel Veillard01fa6152004-06-29 17:04:39 +000010416#if 0 /* Not currently used. */
Daniel Veillard4255d502002-04-16 15:50:10 +000010417/**
10418 * xmlSchemaValidateBasicType:
10419 * @ctxt: a schema validation context
10420 * @node: the top node.
10421 *
10422 * Validate the content of an element expected to be a basic type type
10423 *
10424 * Returns 0 if the element is schemas valid, a positive error code
10425 * number otherwise and -1 in case of internal or API error.
10426 */
10427static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010428xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10429{
Daniel Veillard4255d502002-04-16 15:50:10 +000010430 int ret;
10431 xmlNodePtr child, cur;
10432 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010433 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +000010434
10435 child = ctxt->node;
10436 type = ctxt->type;
10437
10438 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000010439 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10440 "Internal error: xmlSchemaValidateBasicType\n",
10441 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010442 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000010443 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010444 if (type->type != XML_SCHEMA_TYPE_BASIC) {
10445 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10446 "Internal error: xmlSchemaValidateBasicType, "
10447 "the given type is not a built-in type.\n",
10448 node->name, NULL);
10449 return (-1);
10450 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010451 /*
10452 * First check the content model of the node.
10453 */
10454 cur = child;
10455 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010456 switch (cur->type) {
10457 case XML_TEXT_NODE:
10458 case XML_CDATA_SECTION_NODE:
10459 case XML_PI_NODE:
10460 case XML_COMMENT_NODE:
10461 case XML_XINCLUDE_START:
10462 case XML_XINCLUDE_END:
10463 break;
10464 case XML_ENTITY_REF_NODE:
10465 case XML_ENTITY_NODE:
10466 TODO break;
10467 case XML_ELEMENT_NODE:
William M. Bracke7091952004-05-11 15:09:58 +000010468 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
10469 "Element %s: child %s should not be present\n",
10470 node->name, cur->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010471 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010472 case XML_ATTRIBUTE_NODE:
10473 case XML_DOCUMENT_NODE:
10474 case XML_DOCUMENT_TYPE_NODE:
10475 case XML_DOCUMENT_FRAG_NODE:
10476 case XML_NOTATION_NODE:
10477 case XML_HTML_DOCUMENT_NODE:
10478 case XML_DTD_NODE:
10479 case XML_ELEMENT_DECL:
10480 case XML_ATTRIBUTE_DECL:
10481 case XML_ENTITY_DECL:
10482 case XML_NAMESPACE_DECL:
10483#ifdef LIBXML_DOCB_ENABLED
10484 case XML_DOCB_DOCUMENT_NODE:
10485#endif
William M. Bracke7091952004-05-11 15:09:58 +000010486 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
10487 "Element %s: node type of node unexpected here\n",
10488 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010489 return (ctxt->err);
10490 }
10491 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010492 }
10493 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010494 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010495 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010496 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +000010497
10498 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010499 xmlSchemaFreeValue(ctxt->value);
10500 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010501 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010502
Daniel Veillard4255d502002-04-16 15:50:10 +000010503 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
Daniel Veillard01fa6152004-06-29 17:04:39 +000010504
Daniel Veillard4255d502002-04-16 15:50:10 +000010505 if (value != NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010506 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +000010507 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +000010508 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
10509 "Element %s: failed to validate basic type %s\n",
10510 node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010511 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010512 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000010513}
Daniel Veillard01fa6152004-06-29 17:04:39 +000010514#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010515
10516/**
10517 * xmlSchemaValidateComplexType:
10518 * @ctxt: a schema validation context
10519 * @node: the top node.
10520 *
10521 * Validate the content of an element expected to be a complex type type
10522 * xmlschema-1.html#cvc-complex-type
10523 * Validation Rule: Element Locally Valid (Complex Type)
10524 *
10525 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000010526 * number otherwise and -1 in case of internal or API error.
10527 * Note on reported errors: Although it might be nice to report
10528 * the name of the simple/complex type, used to validate the content
10529 * of a node, it is quite unnecessary: for global defined types
10530 * the local name of the element is equal to the NCName of the type,
10531 * for local defined types it makes no sense to output the internal
10532 * computed name of the type. TODO: Instead, one should attach the
10533 * struct of the type involved to the error handler - this allows
10534 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000010535 */
10536static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010537xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10538{
Daniel Veillard4255d502002-04-16 15:50:10 +000010539 xmlNodePtr child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010540 xmlSchemaTypePtr type;
10541 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010542
Daniel Veillard4255d502002-04-16 15:50:10 +000010543 child = ctxt->node;
10544 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000010545 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000010546
Daniel Veillard4255d502002-04-16 15:50:10 +000010547 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010548 case XML_SCHEMA_CONTENT_EMPTY: {
10549 /*
10550 * 1 If the {content type} is empty, then the element information
10551 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000010552 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010553 /* TODO: Hmm, Xerces reports nodes like Comment to be invalid
10554 * content, but XSV does not.
10555 */
10556 /*
10557 * TODO: Is the entity stuff correct?
10558 */
10559 while (child != NULL) {
10560 if ((child->type == XML_ELEMENT_NODE) ||
10561 /*
10562 * TODO: Ask Daniel if this are all character nodes.
10563 */
10564 (child->type == XML_TEXT_NODE) ||
10565 (child->type == XML_CDATA_SECTION_NODE) ||
10566 (child->type == XML_ENTITY_REF_NODE) ||
10567 (child->type == XML_ENTITY_NODE)) {
10568 break;
10569 }
10570 child = child->next;
10571 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010572 if (child != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010573 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
10574 "Character or element children are not allowed, "
10575 "because the content type is empty.\n",
10576 NULL, NULL);
10577 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010578 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010579 }
10580 case XML_SCHEMA_CONTENT_ELEMENTS:
10581 case XML_SCHEMA_CONTENT_MIXED:
10582 while (child != NULL) {
10583 if (child->type == XML_ELEMENT_NODE) {
10584 ret = xmlRegExecPushString(ctxt->regexp,
10585 child->name, child);
10586#ifdef DEBUG_AUTOMATA
10587 if (ret < 0)
10588 xmlGenericError(xmlGenericErrorContext,
10589 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000010590 else
10591 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010592 " --> %s\n", child->name);
10593#endif
10594 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
10595 /*
10596 * TODO: Ask Daniel if this are all character nodes.
10597 */
10598 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
10599 (child->type == XML_ENTITY_NODE) ||
10600 (child->type == XML_ENTITY_REF_NODE) ||
10601 (child->type == XML_CDATA_SECTION_NODE))) {
10602 /*
10603 * 2.3 If the {content type} is element-only, then the
10604 * element information item has no character information
10605 * item [children] other than those whose [character
10606 * code] is defined as a white space in [XML 1.0 (Second
10607 * Edition)].
10608 */
10609 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
10610 "Character children are not allowed, "
10611 "because the content type is element-only.\n",
10612 NULL, NULL);
10613 break;
10614 }
10615 child = child->next;
10616 }
10617 break;
10618 case XML_SCHEMA_CONTENT_SIMPLE:
10619 case XML_SCHEMA_CONTENT_BASIC:{
10620 xmlSchemaTypePtr base, anyType;
10621 xmlChar *value = NULL;
10622 /*
10623 * We hit a complexType with a simpleContent resolving
10624 * to a user derived or built-in simple type.
10625 */
10626 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10627 /*
10628 * Internal check for integrity of the base type.
10629 */
10630 base = type->baseType;
10631 while ((base != NULL) &&
10632 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
10633 (base->type != XML_SCHEMA_TYPE_BASIC) &&
10634 (base != anyType)) {
10635 base = base->baseType;
10636 }
10637 if ((base == NULL) ||
10638 (((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) &&
10639 (base->type != XML_SCHEMA_TYPE_SIMPLE)) ||
10640 ((type->contentType == XML_SCHEMA_CONTENT_BASIC) &&
10641 (base->type != XML_SCHEMA_TYPE_BASIC)))) {
10642 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10643 "Internal error: xmlSchemaValidateComplexType, "
10644 "Element \"%s\": the base type of the corresponding "
10645 "complex type \"%s\" is not a user derived or a "
10646 "built-in simple type.\n",
10647 node->name, type->name);
10648 return (-1);
10649 }
10650 /*
10651 * 2.2 If the {content type} is a simple type definition,
10652 * then the element information item has no element
10653 * information item [children], and the ·normalized value·
10654 * of the element information item is ·valid· with respect
10655 * to that simple type definition as defined by String
10656 * Valid (§3.14.4).
10657 */
10658 child = node->children;
10659 while (child != NULL) {
10660 if (child->type == XML_ELEMENT_NODE) {
10661 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
10662 "Element children are not allowed, because "
10663 "the content type is a simple type.\n",
10664 NULL, NULL);
10665 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
10666 break;
10667 }
10668 child = child->next;
10669 }
10670 if (ret == 0) {
10671 /*
10672 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000010673 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010674 if (ctxt->node == NULL)
10675 value = NULL;
10676 else
10677 value = xmlNodeGetContent(node);
10678 ctxt->type = base;
10679 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1);
10680 ctxt->type = type;
10681 if (ret > 0) {
10682 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
10683 "The character value "
10684 "is not valid with respect to the simple type.\n",
10685 NULL, NULL);
10686 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
10687 } else if (ret < 0) {
10688 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10689 "Internal error: xmlSchemaValidateComplexType, "
10690 "Element \"%s\": error while validating character "
10691 "content against complex type \"%s\".\n",
10692 node->name, type->name);
10693 return (-1);
10694 }
10695 }
10696 if (ret == 0) {
10697 /*
10698 * Apply facets of the complexType. Be sure to pass the
10699 * built-in type to xmlSchemaValidateFacetsInternal.
10700 */
10701 /* TODO: I don't know yet if the facets of the simple type
10702 * are used, or if the facets, defined by this complex type,
10703 * are to be used only. This here applies both facet sets.
10704 */
10705 while (base->type != XML_SCHEMA_TYPE_BASIC)
10706 base = base->baseType;
10707 if (base == NULL) {
10708 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10709 "Internal error: xmlSchemaValidateComplexType, "
10710 "Element \"%s\": error while validating character "
10711 "content against complex type \"%s\"; failed to "
10712 "compute the built-in simple type for facet "
10713 "validation.\n",
10714 node->name, type->name);
10715 return (-1);
10716 }
10717 ret = xmlSchemaValidateFacetsInternal(ctxt, base,
10718 type->facetSet, value, 1);
10719 if (ret > 0) {
10720 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
10721 "The character value "
10722 "is not valid with respect to the simple type.\n",
10723 NULL, NULL);
10724 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
10725 } else if (ret < 0) {
10726 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10727 "Internal error: xmlSchemaValidateComplexType, "
10728 "Element \"%s\": error while validating character "
10729 "content against complex type \"%s\"; failed to "
10730 "apply facets.\n",
10731 type->name, NULL);
10732 }
10733 }
10734 if (value != NULL)
10735 xmlFree(value);
10736 /* TODO: facets */
10737 break;
10738 }
10739 /*
10740 case XML_SCHEMA_CONTENT_SIMPLE:{
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010741 if (type->subtypes != NULL) {
10742 ctxt->type = type->subtypes;
10743 xmlSchemaValidateComplexType(ctxt, node);
10744 }
10745 if (type->baseType != NULL) {
10746 ctxt->type = type->baseType;
10747 xmlSchemaValidateComplexType(ctxt, node);
10748 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010749 * Removed due to changes of attribute validation:
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010750 if (type->attributes != NULL) {
10751 xmlSchemaValidateAttributes(ctxt, node,
10752 type->attributes);
10753 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010754 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010755 ctxt->type = type;
10756 break;
10757 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010758 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010759 default:
10760 TODO xmlGenericError(xmlGenericErrorContext,
10761 "unimplemented content type %d\n",
10762 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000010763 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010764 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010765 xmlSchemaValidateAttributes(ctxt, node, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010766 }
10767 ctxt->cur = node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010768 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010769}
10770
10771/**
10772 * xmlSchemaValidateContent:
10773 * @ctxt: a schema validation context
10774 * @elem: an element
10775 * @type: the type declaration
10776 *
10777 * Validate the content of an element against the type.
10778 *
10779 * Returns 0 if the element is schemas valid, a positive error code
10780 * number otherwise and -1 in case of internal or API error.
10781 */
10782static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010783xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10784{
Daniel Veillard4255d502002-04-16 15:50:10 +000010785 xmlNodePtr child;
10786 xmlSchemaTypePtr type;
10787
10788 child = ctxt->node;
10789 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000010790 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000010791
Daniel Veillard82bbbd42003-05-11 20:16:09 +000010792 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +000010793
Daniel Veillard4255d502002-04-16 15:50:10 +000010794 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010795 case XML_SCHEMA_TYPE_ANY:
10796 /* Any type will do it, fine */
10797 TODO /* handle recursivity */
10798 break;
10799 case XML_SCHEMA_TYPE_COMPLEX:
10800 xmlSchemaValidateComplexType(ctxt, node);
10801 break;
10802 case XML_SCHEMA_TYPE_ELEMENT:{
10803 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
10804
10805 /*
10806 * Handle element reference here
10807 */
10808 if (decl->ref != NULL) {
10809 if (decl->refDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000010810 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10811 "Internal error: element reference %s "
10812 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010813 return (-1);
10814 }
10815 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
10816 decl = decl->refDecl;
10817 }
William M. Bracke7091952004-05-11 15:09:58 +000010818 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010819 xmlSchemaValidateElementType(ctxt, node);
10820 ctxt->type = type;
10821 break;
10822 }
10823 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010824 case XML_SCHEMA_TYPE_SIMPLE:
10825 xmlSchemaValidateSimpleTypeElement(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010826 break;
10827 case XML_SCHEMA_TYPE_FACET:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010828 TODO break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010829 case XML_SCHEMA_TYPE_SEQUENCE:
10830 TODO break;
10831 case XML_SCHEMA_TYPE_CHOICE:
10832 TODO break;
10833 case XML_SCHEMA_TYPE_ALL:
10834 TODO break;
10835 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10836 TODO break;
10837 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10838 TODO break;
10839 case XML_SCHEMA_TYPE_UR:
10840 TODO break;
10841 case XML_SCHEMA_TYPE_RESTRICTION:
10842 /*xmlSchemaValidateRestrictionType(ctxt, node); */
10843 TODO break;
10844 case XML_SCHEMA_TYPE_EXTENSION:
10845 TODO break;
10846 case XML_SCHEMA_TYPE_ATTRIBUTE:
10847 TODO break;
10848 case XML_SCHEMA_TYPE_GROUP:
10849 TODO break;
10850 case XML_SCHEMA_TYPE_NOTATION:
10851 TODO break;
10852 case XML_SCHEMA_TYPE_LIST:
10853 TODO break;
10854 case XML_SCHEMA_TYPE_UNION:
10855 TODO break;
10856 case XML_SCHEMA_FACET_MININCLUSIVE:
10857 TODO break;
10858 case XML_SCHEMA_FACET_MINEXCLUSIVE:
10859 TODO break;
10860 case XML_SCHEMA_FACET_MAXINCLUSIVE:
10861 TODO break;
10862 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
10863 TODO break;
10864 case XML_SCHEMA_FACET_TOTALDIGITS:
10865 TODO break;
10866 case XML_SCHEMA_FACET_FRACTIONDIGITS:
10867 TODO break;
10868 case XML_SCHEMA_FACET_PATTERN:
10869 TODO break;
10870 case XML_SCHEMA_FACET_ENUMERATION:
10871 TODO break;
10872 case XML_SCHEMA_FACET_WHITESPACE:
10873 TODO break;
10874 case XML_SCHEMA_FACET_LENGTH:
10875 TODO break;
10876 case XML_SCHEMA_FACET_MAXLENGTH:
10877 TODO break;
10878 case XML_SCHEMA_FACET_MINLENGTH:
10879 TODO break;
10880 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
10881 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +000010882 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
10883 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +000010884 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010885
10886 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010887 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010888 ctxt->node = ctxt->node->next;
10889 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010890 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010891}
10892
10893/**
10894 * xmlSchemaValidateType:
10895 * @ctxt: a schema validation context
10896 * @elem: an element
10897 * @type: the list of type declarations
10898 *
10899 * Validate the content of an element against the types.
10900 *
10901 * Returns 0 if the element is schemas valid, a positive error code
10902 * number otherwise and -1 in case of internal or API error.
10903 */
10904static int
10905xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010906 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
10907{
Daniel Veillard4255d502002-04-16 15:50:10 +000010908 xmlChar *nil;
10909
Daniel Veillard2db8c122003-07-08 12:16:59 +000010910 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010911 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +000010912
Daniel Veillard3646d642004-06-02 19:19:14 +000010913 /* This one is called by "xmlSchemaValidateElementType" and
10914 * "xmlSchemaValidateElement".
10915 */
10916
Daniel Veillard4255d502002-04-16 15:50:10 +000010917 /*
10918 * 3.3.4 : 2
10919 */
10920 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
William M. Bracke7091952004-05-11 15:09:58 +000010921 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
10922 "Element declaration %s is abstract\n",
10923 elemDecl->name, NULL);
10924 /* Changed, since the element declaration is abstract and not
10925 * the element itself. */
10926 /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
10927 "Element %s is abstract\n", elem->name, NULL); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010928 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010929 }
10930 /*
10931 * 3.3.4: 3
10932 */
10933 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
10934 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010935 /* 3.3.4: 3.2 */
10936 if (xmlStrEqual(nil, BAD_CAST "true")) {
10937 if (elem->children != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000010938 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
10939 "Element %s is not empty\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010940 return (ctxt->err);
10941 }
10942 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
10943 (elemDecl->value != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000010944 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
10945 "Empty element %s cannot get a fixed value\n",
10946 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010947 return (ctxt->err);
10948 }
10949 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010950 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010951 /* 3.3.4: 3.1 */
10952 if (nil != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000010953 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
10954 "Element %s with xs:nil but not nillable\n",
10955 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010956 xmlFree(nil);
10957 return (ctxt->err);
10958 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010959 }
10960
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010961 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +000010962
10963 ctxt->type = elemDecl->subtypes;
10964 ctxt->node = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010965 xmlSchemaValidateContent(ctxt, elem);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010966 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010967}
10968
10969
10970/**
10971 * xmlSchemaValidateAttributes:
10972 * @ctxt: a schema validation context
10973 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000010974 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000010975 *
10976 * Validate the attributes of an element.
10977 *
10978 * Returns 0 if the element is schemas valid, a positive error code
10979 * number otherwise and -1 in case of internal or API error.
10980 */
10981static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010982xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010983{
Daniel Veillard3646d642004-06-02 19:19:14 +000010984 int ret;
10985 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +000010986 xmlChar *value;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000010987 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000010988 xmlSchemaAttributeLinkPtr attrUse;
10989 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000010990 int found;
William M. Brack803812b2004-06-03 02:11:24 +000010991 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000010992#ifdef DEBUG_ATTR_VALIDATION
10993 int redundant = 0;
10994#endif
10995 if (type->type != XML_SCHEMA_TYPE_COMPLEX) {
10996 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INTERNAL,
10997 "Internal error: xmlSchemaValidateAttributes: "
10998 "given type \"%s\"is not a complexType\n",
10999 type->name, NULL);
11000 return(-1);
11001 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011002
Daniel Veillard3646d642004-06-02 19:19:14 +000011003 if ((type->attributeUses == NULL) && (type->attributeWildcard == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011004 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011005
11006 attrUse = type->attributeUses;
11007
11008 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000011009 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011010 attrDecl = attrUse->attr;
11011#ifdef DEBUG_ATTR_VALIDATION
11012 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
11013 printf("attr use - use: %d\n", attrDecl->occurs);
11014#endif
11015 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
11016
11017 if (curState->decl == attrUse->attr) {
11018#ifdef DEBUG_ATTR_VALIDATION
11019 redundant = 1;
11020#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011021 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011022 attr = curState->attr;
11023#ifdef DEBUG_ATTR_VALIDATION
11024 printf("attr - name: %s\n", attr->name);
11025 if (attr->ns != NULL)
11026 printf("attr - ns: %s\n", attr->ns->href);
11027 else
11028 printf("attr - ns: none\n");
11029#endif
11030 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011031 if (attr == NULL)
11032 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000011033 if (attrDecl->ref != NULL) {
11034 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011035 continue;
11036 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011037 if ((attrDecl->refNs == NULL) ||
11038 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011039 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000011040 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011041 continue;
11042 }
11043 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000011044 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011045 continue;
11046 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011047 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011048 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011049 if (attr->ns == NULL) {
11050 /*
William M. Bracke7091952004-05-11 15:09:58 +000011051 * accept an unqualified attribute only if the target
11052 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011053 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011054 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000011055 /*
11056 * This check was removed, since the target namespace
11057 * was evaluated during parsing and already took
11058 * "attributeFormDefault" into account.
11059 */
11060 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011061 continue;
11062 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000011063 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011064 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000011065 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011066 attr->ns->href))
11067 continue;
11068 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011069 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011070#ifdef DEBUG_ATTR_VALIDATION
11071 printf("found\n");
11072#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000011073 found = 1;
Daniel Veillard50355f02004-06-08 17:52:16 +000011074 ctxt->cur = (xmlNodePtr) attr;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011075 ctxt->node = attr->children;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000011076
Daniel Veillard3646d642004-06-02 19:19:14 +000011077 if (attrDecl->subtypes == NULL) {
11078 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
11079 curState->decl = attrDecl;
11080 /*
11081 * This could be put into "xmlSchemaCheckAttributes" as well, but
11082 * since it reports an internal error, it better stays here to ease
11083 * debugging.
11084 */
William M. Bracke7091952004-05-11 15:09:58 +000011085 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
11086 "Internal error: attribute %s type not resolved\n",
11087 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011088 continue;
11089 }
11090 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011091 ctxt->type = attrDecl->subtypes;
11092 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1);
11093 ctxt->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +000011094 if (ret != 0)
11095 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
11096 else
11097 curState->state = XML_SCHEMAS_ATTR_CHECKED;
11098 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011099 if (value != NULL) {
11100 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +000011101 }
11102 }
11103 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11104 xmlSchemaAttrStatePtr tmp;
11105
11106#ifdef DEBUG_ATTR_VALIDATION
11107 printf("required attr not found\n");
11108#endif
11109 /*
11110 * Add a new dummy attribute state.
11111 */
11112 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
11113 if (tmp == NULL) {
11114 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
11115 return (-1);
11116 }
11117 tmp->attr = NULL;
11118 tmp->state = XML_SCHEMAS_ATTR_MISSING;
11119 tmp->decl = attrDecl;
11120 tmp->next = NULL;
11121
11122 if (reqAttrStates == NULL) {
11123 reqAttrStates = tmp;
11124 reqAttrStatesTop = tmp;
11125 } else {
11126 reqAttrStatesTop->next = tmp;
11127 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011128 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011129
11130 }
11131 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011132 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011133 /*
11134 * Add required attributes to the attribute states of the context.
11135 */
11136 if (reqAttrStates != NULL) {
11137 if (ctxt->attr == NULL) {
11138 ctxt->attr = reqAttrStates;
11139 } else {
11140 ctxt->attrTop->next = reqAttrStates;
11141 }
11142 ctxt->attrTop = reqAttrStatesTop;
11143 }
11144 /*
11145 * Process wildcards.
11146 */
11147 if (type->attributeWildcard != NULL) {
11148#ifdef DEBUG_ATTR_VALIDATION
11149 xmlSchemaWildcardNsPtr ns;
11150 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000011151 if (type->attributeWildcard->processContents ==
11152 XML_SCHEMAS_ANY_LAX)
11153 printf("processContents: lax\n");
11154 else if (type->attributeWildcard->processContents ==
11155 XML_SCHEMAS_ANY_STRICT)
11156 printf("processContents: strict\n");
11157 else
11158 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000011159 if (type->attributeWildcard->any)
11160 printf("type: any\n");
11161 else if (type->attributeWildcard->negNsSet != NULL) {
11162 printf("type: negated\n");
11163 if (type->attributeWildcard->negNsSet->value == NULL)
11164 printf("ns: (absent)\n");
11165 else
11166 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
11167 } else if (type->attributeWildcard->nsSet != NULL) {
11168 printf("type: set\n");
11169 ns = type->attributeWildcard->nsSet;
11170 while (ns != NULL) {
11171 if (ns->value == NULL)
11172 printf("ns: (absent)\n");
11173 else
11174 printf("ns: %s\n", ns->value);
11175 ns = ns->next;
11176 }
11177 } else
11178 printf("empty\n");
11179
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000011180
11181#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000011182 curState = ctxt->attr;
11183 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000011184 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
11185 if (curState->attr->ns != NULL)
11186 nsURI = curState->attr->ns->href;
11187 else
11188 nsURI = NULL;
11189 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11190 nsURI)) {
11191 /*
11192 * Handle processContents.
11193 */
11194 if ((type->attributeWildcard->processContents ==
11195 XML_SCHEMAS_ANY_LAX) ||
11196 (type->attributeWildcard->processContents ==
11197 XML_SCHEMAS_ANY_STRICT)) {
11198
11199 attr = curState->attr;
11200 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
11201 attr->name, nsURI);
11202 if (attrDecl != NULL) {
11203 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011204 ctxt->type = attrDecl->subtypes;
11205 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1);
11206 ctxt->type = type;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000011207 if (ret != 0)
11208 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
11209 else
11210 curState->state = XML_SCHEMAS_ATTR_CHECKED;
11211 curState->decl = attrDecl;
11212 if (value != NULL) {
11213 xmlFree(value);
11214 }
11215
11216 } else if (type->attributeWildcard->processContents ==
11217 XML_SCHEMAS_ANY_LAX) {
11218 curState->state = XML_SCHEMAS_ATTR_CHECKED;
11219 }
11220 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000011221 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000011222 }
11223 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011224 curState = curState->next;
11225 }
11226 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011227#ifdef DEBUG_ATTR_VALIDATION
11228 if (redundant)
11229 xmlGenericError(xmlGenericErrorContext,
11230 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
11231 type->name);
11232#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011233 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011234}
11235
11236/**
11237 * xmlSchemaValidateElement:
11238 * @ctxt: a schema validation context
11239 * @elem: an element
11240 *
11241 * Validate an element in a tree
11242 *
11243 * Returns 0 if the element is schemas valid, a positive error code
11244 * number otherwise and -1 in case of internal or API error.
11245 */
11246static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011247xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
11248{
Daniel Veillard4255d502002-04-16 15:50:10 +000011249 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +000011250 int ret;
11251 xmlSchemaAttrStatePtr attrs, attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000011252
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011253 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011254 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11255 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011256 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011257 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11258 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011259 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011260 /* This one is called by xmlSchemaValidateDocument only. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011261
Daniel Veillard4255d502002-04-16 15:50:10 +000011262 /*
11263 * 3.3.4 : 1
11264 */
11265 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000011266 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
11267 "Element %s not declared\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011268 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011269 }
11270 if (elemDecl->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000011271 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
11272 "Element %s has no type\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011273 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011274 }
11275 /*
11276 * Verify the attributes
11277 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011278 attrs = ctxt->attr;
11279 attrTop = ctxt->attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000011280 xmlSchemaRegisterAttributes(ctxt, elem->properties);
Daniel Veillard4255d502002-04-16 15:50:10 +000011281 /*
11282 * Verify the element content recursively
11283 */
11284 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011285 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
11286 (xmlRegExecCallbacks)
11287 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011288#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011289 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011290#endif
11291 }
11292 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011293 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011294 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011295#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011296 xmlGenericError(xmlGenericErrorContext,
11297 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011298#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011299 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000011300 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
11301 "Element %s content check failed\n",
11302 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011303 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +000011304 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
11305 "Element %s content check failed\n",
11306 elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011307#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011308 } else {
11309 xmlGenericError(xmlGenericErrorContext,
11310 "Element %s content check succeeded\n",
11311 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011312
11313#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011314 }
11315 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000011316 }
11317 /*
11318 * Verify that all attributes were Schemas-validated
11319 */
11320 xmlSchemaCheckAttributes(ctxt, elem);
Daniel Veillard3646d642004-06-02 19:19:14 +000011321 if (ctxt->attr != NULL)
11322 xmlSchemaFreeAttributeStates(ctxt->attr);
11323 ctxt->attr = attrs;
11324 ctxt->attrTop = attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011325
11326 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011327}
11328
11329/**
11330 * xmlSchemaValidateDocument:
11331 * @ctxt: a schema validation context
11332 * @doc: a parsed document tree
11333 *
11334 * Validate a document tree in memory.
11335 *
11336 * Returns 0 if the document is schemas valid, a positive error code
11337 * number otherwise and -1 in case of internal or API error.
11338 */
11339static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011340xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
11341{
Daniel Veillard4255d502002-04-16 15:50:10 +000011342 xmlNodePtr root;
11343 xmlSchemaElementPtr elemDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011344
Daniel Veillard4255d502002-04-16 15:50:10 +000011345 root = xmlDocGetRootElement(doc);
11346 if (root == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000011347 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
11348 "document has no root\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011349 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011350 }
William M. Bracke7091952004-05-11 15:09:58 +000011351
Daniel Veillard4255d502002-04-16 15:50:10 +000011352 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011353 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11354 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011355 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011356 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11357 root->name, NULL, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011358
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011359 /*
11360 * special case whe elementFormDefault is unqualified for top-level elem.
11361 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011362 /* Removed, since elementFormDefault does not apply to top level
11363 * elements */
11364 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011365 if ((elemDecl == NULL) && (root->ns != NULL) &&
11366 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
11367 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
11368 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11369 root->name, NULL, NULL);
11370 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011371 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011372
Daniel Veillard4255d502002-04-16 15:50:10 +000011373 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000011374 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
11375 "Element %s not declared\n", root->name, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011376 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000011377 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
Daniel Veillard3646d642004-06-02 19:19:14 +000011378 "Root element %s not global\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011379 }
11380 /*
11381 * Okay, start the recursive validation
11382 */
11383 xmlSchemaValidateElement(ctxt, root);
11384
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011385 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011386}
11387
11388/************************************************************************
11389 * *
11390 * SAX Validation code *
11391 * *
11392 ************************************************************************/
11393
11394/************************************************************************
11395 * *
11396 * Validation interfaces *
11397 * *
11398 ************************************************************************/
11399
11400/**
11401 * xmlSchemaNewValidCtxt:
11402 * @schema: a precompiled XML Schemas
11403 *
11404 * Create an XML Schemas validation context based on the given schema
11405 *
11406 * Returns the validation context or NULL in case of error
11407 */
11408xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011409xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
11410{
Daniel Veillard4255d502002-04-16 15:50:10 +000011411 xmlSchemaValidCtxtPtr ret;
11412
11413 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
11414 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011415 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011416 return (NULL);
11417 }
11418 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
11419 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000011420 /*
11421 * Removed due to changes of the attribute state list.
William M. Brack803812b2004-06-03 02:11:24 +000011422 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011423 /* ret->attrNr = 0; */
11424 /* ret->attrMax = 10; */
11425 /* ret->attrBase = NULL; */
11426 ret->attrTop = NULL;
11427 ret->attr = NULL;
11428 /*
11429 * Removed due to changes of the attribute state list.
William M. Brack803812b2004-06-03 02:11:24 +000011430 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011431 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011432 sizeof
11433 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +000011434 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011435 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
11436 free(ret);
11437 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011438 }
11439 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
Daniel Veillard3646d642004-06-02 19:19:14 +000011440 */
11441
Daniel Veillard4255d502002-04-16 15:50:10 +000011442 return (ret);
11443}
11444
11445/**
11446 * xmlSchemaFreeValidCtxt:
11447 * @ctxt: the schema validation context
11448 *
11449 * Free the resources associated to the schema validation context
11450 */
11451void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011452xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
11453{
Daniel Veillard4255d502002-04-16 15:50:10 +000011454 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011455 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011456 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011457 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000011458 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011459 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +000011460 xmlFree(ctxt);
11461}
11462
11463/**
11464 * xmlSchemaSetValidErrors:
11465 * @ctxt: a schema validation context
11466 * @err: the error function
11467 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000011468 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000011469 *
11470 * Set the error and warning callback informations
11471 */
11472void
11473xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011474 xmlSchemaValidityErrorFunc err,
11475 xmlSchemaValidityWarningFunc warn, void *ctx)
11476{
Daniel Veillard4255d502002-04-16 15:50:10 +000011477 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011478 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011479 ctxt->error = err;
11480 ctxt->warning = warn;
11481 ctxt->userData = ctx;
11482}
11483
11484/**
11485 * xmlSchemaValidateDoc:
11486 * @ctxt: a schema validation context
11487 * @doc: a parsed document tree
11488 *
11489 * Validate a document tree in memory.
11490 *
11491 * Returns 0 if the document is schemas valid, a positive error code
11492 * number otherwise and -1 in case of internal or API error.
11493 */
11494int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011495xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
11496{
Daniel Veillard4255d502002-04-16 15:50:10 +000011497 int ret;
11498
11499 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011500 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011501
11502 ctxt->doc = doc;
11503 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011504 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000011505}
11506
11507/**
11508 * xmlSchemaValidateStream:
11509 * @ctxt: a schema validation context
11510 * @input: the input to use for reading the data
11511 * @enc: an optional encoding information
11512 * @sax: a SAX handler for the resulting events
11513 * @user_data: the context to provide to the SAX handler.
11514 *
11515 * Validate a document tree in memory.
11516 *
11517 * Returns 0 if the document is schemas valid, a positive error code
11518 * number otherwise and -1 in case of internal or API error.
11519 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011520int
Daniel Veillard4255d502002-04-16 15:50:10 +000011521xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011522 xmlParserInputBufferPtr input, xmlCharEncoding enc,
11523 xmlSAXHandlerPtr sax, void *user_data)
11524{
Daniel Veillard4255d502002-04-16 15:50:10 +000011525 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011526 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011527 ctxt->input = input;
11528 ctxt->enc = enc;
11529 ctxt->sax = sax;
11530 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011531 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011532}
11533
11534#endif /* LIBXML_SCHEMAS_ENABLED */