blob: 59cfee029a27387b7707196e1caa53c957fd5301 [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);
Daniel Veillard4e5d6652004-06-29 21:01:12 +0000774 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000775 xmlFree(type);
776}
777
778/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000779 * xmlSchemaFreeTypeList:
780 * @type: a schema type structure
781 *
782 * Deallocate a Schema Type structure.
783 */
784static void
785xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
786{
787 xmlSchemaTypePtr next;
788
789 while (type != NULL) {
790 next = type->redef;
791 xmlSchemaFreeType(type);
792 type = next;
793 }
794}
795
796/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000797 * xmlSchemaFree:
798 * @schema: a schema structure
799 *
800 * Deallocate a Schema structure.
801 */
802void
803xmlSchemaFree(xmlSchemaPtr schema)
804{
805 if (schema == NULL)
806 return;
807
Daniel Veillard4255d502002-04-16 15:50:10 +0000808 if (schema->notaDecl != NULL)
809 xmlHashFree(schema->notaDecl,
810 (xmlHashDeallocator) xmlSchemaFreeNotation);
811 if (schema->attrDecl != NULL)
812 xmlHashFree(schema->attrDecl,
813 (xmlHashDeallocator) xmlSchemaFreeAttribute);
814 if (schema->attrgrpDecl != NULL)
815 xmlHashFree(schema->attrgrpDecl,
816 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
817 if (schema->elemDecl != NULL)
818 xmlHashFree(schema->elemDecl,
819 (xmlHashDeallocator) xmlSchemaFreeElement);
820 if (schema->typeDecl != NULL)
821 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000822 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000823 if (schema->groupDecl != NULL)
824 xmlHashFree(schema->groupDecl,
825 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +0000826 if (schema->schemasImports != NULL)
827 xmlHashFree(schema->schemasImports,
828 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000829 if (schema->includes != NULL) {
830 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
831 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000832 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000833 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +0000834 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000835 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000836 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000837
838 xmlFree(schema);
839}
840
841/************************************************************************
842 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000843 * Debug functions *
844 * *
845 ************************************************************************/
846
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000847#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000848
Daniel Veillard4255d502002-04-16 15:50:10 +0000849/**
850 * xmlSchemaElementDump:
851 * @elem: an element
852 * @output: the file output
853 *
854 * Dump the element
855 */
856static void
857xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000858 const xmlChar * name ATTRIBUTE_UNUSED,
859 const xmlChar * context ATTRIBUTE_UNUSED,
860 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000861{
862 if (elem == NULL)
863 return;
864
865 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +0000866 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
867 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000868 fprintf(output, ": %s ", elem->name);
869 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000870 fprintf(output, "namespace '%s' ", namespace);
871
Daniel Veillard4255d502002-04-16 15:50:10 +0000872 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000873 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000874 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000875 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000876 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000877 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000878 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000879 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000880 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000881 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000882 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000883 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000884 fprintf(output, "\n");
885 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000886 fprintf(output, " ");
887 if (elem->minOccurs != 1)
888 fprintf(output, "min: %d ", elem->minOccurs);
889 if (elem->maxOccurs >= UNBOUNDED)
890 fprintf(output, "max: unbounded\n");
891 else if (elem->maxOccurs != 1)
892 fprintf(output, "max: %d\n", elem->maxOccurs);
893 else
894 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000895 }
896 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000897 fprintf(output, " type: %s", elem->namedType);
898 if (elem->namedTypeNs != NULL)
899 fprintf(output, " ns %s\n", elem->namedTypeNs);
900 else
901 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000902 }
903 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000904 fprintf(output, " substitutionGroup: %s", elem->substGroup);
905 if (elem->substGroupNs != NULL)
906 fprintf(output, " ns %s\n", elem->substGroupNs);
907 else
908 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000909 }
910 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000911 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000912}
913
914/**
915 * xmlSchemaAnnotDump:
916 * @output: the file output
917 * @annot: a annotation
918 *
919 * Dump the annotation
920 */
921static void
922xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
923{
924 xmlChar *content;
925
926 if (annot == NULL)
927 return;
928
929 content = xmlNodeGetContent(annot->content);
930 if (content != NULL) {
931 fprintf(output, " Annot: %s\n", content);
932 xmlFree(content);
933 } else
934 fprintf(output, " Annot: empty\n");
935}
936
937/**
938 * xmlSchemaTypeDump:
939 * @output: the file output
940 * @type: a type structure
941 *
942 * Dump a SchemaType structure
943 */
944static void
945xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
946{
947 if (type == NULL) {
948 fprintf(output, "Type: NULL\n");
949 return;
950 }
951 fprintf(output, "Type: ");
952 if (type->name != NULL)
953 fprintf(output, "%s, ", type->name);
954 else
955 fprintf(output, "no name");
956 switch (type->type) {
957 case XML_SCHEMA_TYPE_BASIC:
958 fprintf(output, "basic ");
959 break;
960 case XML_SCHEMA_TYPE_SIMPLE:
961 fprintf(output, "simple ");
962 break;
963 case XML_SCHEMA_TYPE_COMPLEX:
964 fprintf(output, "complex ");
965 break;
966 case XML_SCHEMA_TYPE_SEQUENCE:
967 fprintf(output, "sequence ");
968 break;
969 case XML_SCHEMA_TYPE_CHOICE:
970 fprintf(output, "choice ");
971 break;
972 case XML_SCHEMA_TYPE_ALL:
973 fprintf(output, "all ");
974 break;
975 case XML_SCHEMA_TYPE_UR:
976 fprintf(output, "ur ");
977 break;
978 case XML_SCHEMA_TYPE_RESTRICTION:
979 fprintf(output, "restriction ");
980 break;
981 case XML_SCHEMA_TYPE_EXTENSION:
982 fprintf(output, "extension ");
983 break;
984 default:
985 fprintf(output, "unknowntype%d ", type->type);
986 break;
987 }
988 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000989 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000990 }
991 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000992 case XML_SCHEMA_CONTENT_UNKNOWN:
993 fprintf(output, "unknown ");
994 break;
995 case XML_SCHEMA_CONTENT_EMPTY:
996 fprintf(output, "empty ");
997 break;
998 case XML_SCHEMA_CONTENT_ELEMENTS:
999 fprintf(output, "element ");
1000 break;
1001 case XML_SCHEMA_CONTENT_MIXED:
1002 fprintf(output, "mixed ");
1003 break;
1004 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00001005 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001006 break;
1007 case XML_SCHEMA_CONTENT_BASIC:
1008 fprintf(output, "basic ");
1009 break;
1010 case XML_SCHEMA_CONTENT_SIMPLE:
1011 fprintf(output, "simple ");
1012 break;
1013 case XML_SCHEMA_CONTENT_ANY:
1014 fprintf(output, "any ");
1015 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00001016 }
1017 fprintf(output, "\n");
1018 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001019 fprintf(output, " ");
1020 if (type->minOccurs != 1)
1021 fprintf(output, "min: %d ", type->minOccurs);
1022 if (type->maxOccurs >= UNBOUNDED)
1023 fprintf(output, "max: unbounded\n");
1024 else if (type->maxOccurs != 1)
1025 fprintf(output, "max: %d\n", type->maxOccurs);
1026 else
1027 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00001028 }
1029 if (type->annot != NULL)
1030 xmlSchemaAnnotDump(output, type->annot);
1031 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001032 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00001033
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001034 fprintf(output, " subtypes: ");
1035 while (sub != NULL) {
1036 fprintf(output, "%s ", sub->name);
1037 sub = sub->next;
1038 }
1039 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00001040 }
1041
1042}
1043
1044/**
1045 * xmlSchemaDump:
1046 * @output: the file output
1047 * @schema: a schema structure
1048 *
1049 * Dump a Schema structure.
1050 */
1051void
1052xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
1053{
1054 if (schema == NULL) {
1055 fprintf(output, "Schemas: NULL\n");
1056 return;
1057 }
1058 fprintf(output, "Schemas: ");
1059 if (schema->name != NULL)
1060 fprintf(output, "%s, ", schema->name);
1061 else
1062 fprintf(output, "no name, ");
1063 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001064 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001065 else
1066 fprintf(output, "no target namespace");
1067 fprintf(output, "\n");
1068 if (schema->annot != NULL)
1069 xmlSchemaAnnotDump(output, schema->annot);
1070
1071 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
1072 output);
1073 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001074 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00001075}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001076#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00001077
1078/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001079 * *
1080 * Utilities *
1081 * *
1082 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001083
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00001084static xmlAttrPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +00001085xmlSchemaGetPropNode(xmlNodePtr node, const xmlChar *name)
1086{
1087 xmlAttrPtr prop;
1088
1089 if ((node == NULL) || (name == NULL)) return(NULL);
1090 prop = node->properties;
1091 while (prop != NULL) {
1092 if ((xmlStrEqual(prop->name, name)) &&
1093 (prop->ns == NULL))
1094 return(prop);
1095 prop = prop->next;
1096 }
1097 return (NULL);
1098}
1099
1100static const xmlChar *
1101xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1102{
1103 xmlChar *val;
1104 const xmlChar *ret;
1105
1106 val = xmlNodeGetContent(node);
1107 if (val == NULL)
1108 return(NULL);
1109 ret = xmlDictLookup(ctxt->dict, val, -1);
1110 xmlFree(val);
1111 return(ret);
1112}
1113
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001114/**
1115 * xmlSchemaGetProp:
1116 * @ctxt: the parser context
1117 * @node: the node
1118 * @name: the property name
1119 *
1120 * Read a attribute value and internalize the string
1121 *
1122 * Returns the string or NULL if not present.
1123 */
1124static const xmlChar *
1125xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1126 const char *name)
1127{
1128 xmlChar *val;
1129 const xmlChar *ret;
1130
1131 val = xmlGetProp(node, BAD_CAST name);
1132 if (val == NULL)
1133 return(NULL);
1134 ret = xmlDictLookup(ctxt->dict, val, -1);
1135 xmlFree(val);
1136 return(ret);
1137}
1138
William M. Brack29aa7722004-05-12 00:27:56 +00001139#if 0
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001140/**
1141 * xmlSchemaGetNamespace:
1142 * @ctxt: the parser context
1143 * @schema: the schemas containing the declaration
1144 * @node: the node
1145 * @qname: the QName to analyze
1146 *
1147 * Find the namespace name for the given declaration.
1148 *
1149 * Returns the local name for that declaration, as well as the namespace name
William M. Bracke7091952004-05-11 15:09:58 +00001150 * NOTE: This function is no longer used (Buchcik, May '04)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001151 */
1152static const xmlChar *
1153xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1154 xmlNodePtr node, const xmlChar *qname,
1155 const xmlChar **namespace) {
1156 int len;
1157 const xmlChar *name, *prefix, *def = NULL;
1158 xmlNsPtr ns;
1159
1160 *namespace = NULL;
1161
William M. Bracke7091952004-05-11 15:09:58 +00001162 /* TODO: The following seems to be not correct here:
1163 * 1. The name of a declaration is a NCName, not a QName.
1164 * 2. The attribute "targetNamespace" is allowed for the
1165 * <schema> Element Information Item only.
1166 * 3. One cannot evaluate the target namespace, by the type
1167 * of declaration, since it is dependant on the xxxFormDefault
1168 * of <schema> and the form attribute of an <element> or <attribute>.
1169 */
1170
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001171 if (xmlStrEqual(node->name, BAD_CAST "element") ||
1172 xmlStrEqual(node->name, BAD_CAST "attribute") ||
1173 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
1174 xmlStrEqual(node->name, BAD_CAST "complexType")) {
1175 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
1176 }
1177
William M. Bracke7091952004-05-11 15:09:58 +00001178
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001179 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
1180 name = xmlSplitQName3(qname, &len);
1181 if (name == NULL) {
1182 if (def == NULL) {
1183 if (xmlStrEqual(node->name, BAD_CAST "element")) {
1184 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
1185 *namespace = schema->targetNamespace;
1186 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
1187 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
1188 *namespace = schema->targetNamespace;
1189 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
1190 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
1191 *namespace = schema->targetNamespace;
1192 }
1193 } else {
1194 *namespace = def;
1195 }
1196 return(qname);
1197 }
William M. Bracke7091952004-05-11 15:09:58 +00001198
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001199 name = xmlDictLookup(ctxt->dict, name, -1);
1200 prefix = xmlDictLookup(ctxt->dict, qname, len);
1201 if (def != NULL) {
1202 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
1203 "%s: presence of both prefix %s and targetNamespace\n",
1204 node->name, prefix);
1205 }
1206 ns = xmlSearchNs(node->doc, node, prefix);
1207 if (ns == NULL) {
1208 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1209 "%s: the QName prefix %s is undefined\n",
1210 node->name, prefix);
1211 return(name);
1212 }
1213 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1214 return(name);
1215}
William M. Brack29aa7722004-05-12 00:27:56 +00001216#endif
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001217
1218/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00001219 * *
1220 * Parsing functions *
1221 * *
1222 ************************************************************************/
1223
1224/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001225 * xmlSchemaGetElem:
1226 * @schema: the schemas context
1227 * @name: the element name
1228 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001229 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001230 *
1231 * Lookup a an element in the schemas or the accessible schemas
1232 *
1233 * Returns the element definition or NULL if not found.
1234 */
1235static xmlSchemaElementPtr
1236xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001237 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001238{
1239 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001240 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001241
1242 if ((name == NULL) || (schema == NULL))
1243 return (NULL);
1244
Daniel Veillard3646d642004-06-02 19:19:14 +00001245
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001246 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001247 if ((ret != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00001248 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_GLOBAL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001249 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00001250 } else
1251 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00001252 /*
1253 * This one was removed, since top level element declarations have
1254 * the target namespace specified in targetNamespace of the <schema>
1255 * information element, even if elementFormDefault is "unqualified".
1256 */
1257
1258 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001259 if (xmlStrEqual(namespace, schema->targetNamespace))
1260 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1261 else
1262 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001263 if ((ret != NULL) &&
1264 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001265 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001266 }
William M. Bracke7091952004-05-11 15:09:58 +00001267 */
Daniel Veillard3646d642004-06-02 19:19:14 +00001268
1269 /* if (level > 0) */
1270 if (namespace == NULL)
1271 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1272 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001273 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001274 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00001275 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00001276 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
1277 return (ret);
1278 } else
1279 ret = NULL;
1280 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001281#ifdef DEBUG
1282 if (ret == NULL) {
1283 if (namespace == NULL)
1284 fprintf(stderr, "Unable to lookup type %s", name);
1285 else
1286 fprintf(stderr, "Unable to lookup type %s:%s", name,
1287 namespace);
1288 }
1289#endif
1290 return (ret);
1291}
1292
1293/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001294 * xmlSchemaGetType:
1295 * @schema: the schemas context
1296 * @name: the type name
1297 * @ns: the type namespace
1298 *
1299 * Lookup a type in the schemas or the predefined types
1300 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001301 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001302 */
1303static xmlSchemaTypePtr
1304xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001305 const xmlChar * namespace)
1306{
Daniel Veillard4255d502002-04-16 15:50:10 +00001307 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001308 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001309
1310 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001311 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001312 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001313 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001314 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001315 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001316 }
1317 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001318 if (ret != NULL)
1319 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00001320 if (namespace == NULL)
1321 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1322 else
Daniel Veillard1d913862003-11-21 00:28:39 +00001323 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001324 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00001325 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001326 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1327 return (ret);
1328 } else
1329 ret = NULL;
1330 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001331#ifdef DEBUG
1332 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001333 if (namespace == NULL)
1334 fprintf(stderr, "Unable to lookup type %s", name);
1335 else
1336 fprintf(stderr, "Unable to lookup type %s:%s", name,
1337 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001338 }
1339#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001340 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001341}
1342
Daniel Veillard3646d642004-06-02 19:19:14 +00001343/**
1344 * xmlSchemaGetAttribute:
1345 * @schema: the context of the schema
1346 * @name: the name of the attribute
1347 * @ns: the target namespace of the attribute
1348 *
1349 * Lookup a an attribute in the schema or imported schemas
1350 *
1351 * Returns the attribute declaration or NULL if not found.
1352 */
1353static xmlSchemaAttributePtr
1354xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
1355 const xmlChar * namespace)
1356{
1357 xmlSchemaAttributePtr ret;
1358 xmlSchemaImportPtr import = NULL;
1359
1360 if ((name == NULL) || (schema == NULL))
1361 return (NULL);
1362
1363
1364 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
1365 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
1366 return (ret);
1367 else
1368 ret = NULL;
1369 if (namespace == NULL)
1370 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1371 else
1372 import = xmlHashLookup(schema->schemasImports, namespace);
1373 if (import != NULL) {
1374 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
1375 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
1376 return (ret);
1377 } else
1378 ret = NULL;
1379 }
1380#ifdef DEBUG
1381 if (ret == NULL) {
1382 if (namespace == NULL)
1383 fprintf(stderr, "Unable to lookup attribute %s", name);
1384 else
1385 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
1386 namespace);
1387 }
1388#endif
1389 return (ret);
1390}
1391
1392/**
1393 * xmlSchemaGetAttributeGroup:
1394 * @schema: the context of the schema
1395 * @name: the name of the attribute group
1396 * @ns: the target namespace of the attribute group
1397 *
1398 * Lookup a an attribute group in the schema or imported schemas
1399 *
1400 * Returns the attribute group definition or NULL if not found.
1401 */
1402static xmlSchemaAttributeGroupPtr
1403xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
1404 const xmlChar * namespace)
1405{
1406 xmlSchemaAttributeGroupPtr ret;
1407 xmlSchemaImportPtr import = NULL;
1408
1409 if ((name == NULL) || (schema == NULL))
1410 return (NULL);
1411
1412
1413 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
1414 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
1415 return (ret);
1416 else
1417 ret = NULL;
1418 if (namespace == NULL)
1419 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1420 else
1421 import = xmlHashLookup(schema->schemasImports, namespace);
1422 if (import != NULL) {
1423 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
1424 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
1425 return (ret);
1426 else
1427 ret = NULL;
1428 }
1429#ifdef DEBUG
1430 if (ret == NULL) {
1431 if (namespace == NULL)
1432 fprintf(stderr, "Unable to lookup attribute group %s", name);
1433 else
1434 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
1435 namespace);
1436 }
1437#endif
1438 return (ret);
1439}
1440
1441/**
1442 * xmlSchemaGetGroup:
1443 * @schema: the context of the schema
1444 * @name: the name of the group
1445 * @ns: the target namespace of the group
1446 *
1447 * Lookup a group in the schema or imported schemas
1448 *
1449 * Returns the group definition or NULL if not found.
1450 */
1451static xmlSchemaTypePtr
1452xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
1453 const xmlChar * namespace)
1454{
1455 xmlSchemaTypePtr ret;
1456 xmlSchemaImportPtr import = NULL;
1457
1458 if ((name == NULL) || (schema == NULL))
1459 return (NULL);
1460
1461
1462 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
1463 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
1464 return (ret);
1465 else
1466 ret = NULL;
1467 if (namespace == NULL)
1468 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1469 else
1470 import = xmlHashLookup(schema->schemasImports, namespace);
1471 if (import != NULL) {
1472 ret = xmlSchemaGetGroup(import->schema, name, namespace);
1473 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
1474 return (ret);
1475 else
1476 ret = NULL;
1477 }
1478#ifdef DEBUG
1479 if (ret == NULL) {
1480 if (namespace == NULL)
1481 fprintf(stderr, "Unable to lookup group %s", name);
1482 else
1483 fprintf(stderr, "Unable to lookup group %s:%s", name,
1484 namespace);
1485 }
1486#endif
1487 return (ret);
1488}
1489
Daniel Veillard4255d502002-04-16 15:50:10 +00001490/************************************************************************
1491 * *
1492 * Parsing functions *
1493 * *
1494 ************************************************************************/
1495
1496#define IS_BLANK_NODE(n) \
1497 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1498
1499/**
1500 * xmlSchemaIsBlank:
1501 * @str: a string
1502 *
1503 * Check if a string is ignorable
1504 *
1505 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1506 */
1507static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001508xmlSchemaIsBlank(xmlChar * str)
1509{
Daniel Veillard4255d502002-04-16 15:50:10 +00001510 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001511 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001512 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001513 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001514 return (0);
1515 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001516 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001517 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001518}
1519
1520/**
1521 * xmlSchemaAddNotation:
1522 * @ctxt: a schema validation context
1523 * @schema: the schema being built
1524 * @name: the item name
1525 *
1526 * Add an XML schema Attrribute declaration
1527 * *WARNING* this interface is highly subject to change
1528 *
1529 * Returns the new struture or NULL in case of error
1530 */
1531static xmlSchemaNotationPtr
1532xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001533 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001534{
1535 xmlSchemaNotationPtr ret = NULL;
1536 int val;
1537
1538 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1539 return (NULL);
1540
1541 if (schema->notaDecl == NULL)
1542 schema->notaDecl = xmlHashCreate(10);
1543 if (schema->notaDecl == NULL)
1544 return (NULL);
1545
1546 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1547 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001548 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001549 return (NULL);
1550 }
1551 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001552 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001553 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1554 ret);
1555 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001556 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1557 XML_SCHEMAP_REDEFINED_NOTATION,
1558 "Notation %s already defined\n",
1559 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001560 xmlFree(ret);
1561 return (NULL);
1562 }
1563 return (ret);
1564}
1565
1566
1567/**
1568 * xmlSchemaAddAttribute:
1569 * @ctxt: a schema validation context
1570 * @schema: the schema being built
1571 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001572 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001573 *
1574 * Add an XML schema Attrribute declaration
1575 * *WARNING* this interface is highly subject to change
1576 *
1577 * Returns the new struture or NULL in case of error
1578 */
1579static xmlSchemaAttributePtr
1580xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001581 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001582{
1583 xmlSchemaAttributePtr ret = NULL;
1584 int val;
1585
1586 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1587 return (NULL);
1588
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001589#ifdef DEBUG
1590 fprintf(stderr, "Adding attribute %s\n", name);
1591 if (namespace != NULL)
1592 fprintf(stderr, " target namespace %s\n", namespace);
1593#endif
1594
Daniel Veillard4255d502002-04-16 15:50:10 +00001595 if (schema->attrDecl == NULL)
1596 schema->attrDecl = xmlHashCreate(10);
1597 if (schema->attrDecl == NULL)
1598 return (NULL);
1599
1600 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1601 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001602 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001603 return (NULL);
1604 }
1605 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001606 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1607 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001608 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001609 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001610 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001611 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1612 XML_SCHEMAP_REDEFINED_ATTR,
1613 "Attribute %s already defined\n",
1614 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001615 xmlFree(ret);
1616 return (NULL);
1617 }
1618 return (ret);
1619}
1620
1621/**
1622 * xmlSchemaAddAttributeGroup:
1623 * @ctxt: a schema validation context
1624 * @schema: the schema being built
1625 * @name: the item name
1626 *
1627 * Add an XML schema Attrribute Group declaration
1628 *
1629 * Returns the new struture or NULL in case of error
1630 */
1631static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001632xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1633 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001634{
1635 xmlSchemaAttributeGroupPtr ret = NULL;
1636 int val;
1637
1638 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1639 return (NULL);
1640
1641 if (schema->attrgrpDecl == NULL)
1642 schema->attrgrpDecl = xmlHashCreate(10);
1643 if (schema->attrgrpDecl == NULL)
1644 return (NULL);
1645
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001646 ret =
1647 (xmlSchemaAttributeGroupPtr)
1648 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001649 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001650 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001651 return (NULL);
1652 }
1653 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001654 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001655 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001656 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001657 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001658 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1659 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1660 "Attribute group %s already defined\n",
1661 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001662 xmlFree(ret);
1663 return (NULL);
1664 }
1665 return (ret);
1666}
1667
1668/**
1669 * xmlSchemaAddElement:
1670 * @ctxt: a schema validation context
1671 * @schema: the schema being built
1672 * @name: the type name
1673 * @namespace: the type namespace
1674 *
1675 * Add an XML schema Element declaration
1676 * *WARNING* this interface is highly subject to change
1677 *
1678 * Returns the new struture or NULL in case of error
1679 */
1680static xmlSchemaElementPtr
1681xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1682 const xmlChar * name, const xmlChar * namespace)
1683{
1684 xmlSchemaElementPtr ret = NULL;
1685 int val;
1686
1687 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1688 return (NULL);
1689
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001690#ifdef DEBUG
1691 fprintf(stderr, "Adding element %s\n", name);
1692 if (namespace != NULL)
1693 fprintf(stderr, " target namespace %s\n", namespace);
1694#endif
1695
Daniel Veillard4255d502002-04-16 15:50:10 +00001696 if (schema->elemDecl == NULL)
1697 schema->elemDecl = xmlHashCreate(10);
1698 if (schema->elemDecl == NULL)
1699 return (NULL);
1700
1701 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1702 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001703 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001704 return (NULL);
1705 }
1706 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001707 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1708 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001709 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001710 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001711 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001712 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001713
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001714 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001715 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1716 namespace, ret);
1717 if (val != 0) {
1718 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1719 XML_SCHEMAP_REDEFINED_ELEMENT,
1720 "Element %s already defined\n",
1721 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001722 xmlFree(ret);
1723 return (NULL);
1724 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001725 }
1726 return (ret);
1727}
1728
1729/**
1730 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001731 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00001732 * @schema: the schema being built
1733 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001734 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001735 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001736 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00001737 * *WARNING* this interface is highly subject to change
1738 *
1739 * Returns the new struture or NULL in case of error
1740 */
1741static xmlSchemaTypePtr
1742xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001743 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001744{
1745 xmlSchemaTypePtr ret = NULL;
1746 int val;
1747
1748 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1749 return (NULL);
1750
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001751#ifdef DEBUG
1752 fprintf(stderr, "Adding type %s\n", name);
1753 if (namespace != NULL)
1754 fprintf(stderr, " target namespace %s\n", namespace);
1755#endif
1756
Daniel Veillard4255d502002-04-16 15:50:10 +00001757 if (schema->typeDecl == NULL)
1758 schema->typeDecl = xmlHashCreate(10);
1759 if (schema->typeDecl == NULL)
1760 return (NULL);
1761
1762 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1763 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001764 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001765 return (NULL);
1766 }
1767 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001768 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001769 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001770 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001771 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001772 if (ctxt->includes == 0) {
1773 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1774 XML_SCHEMAP_REDEFINED_TYPE,
1775 "Type %s already defined\n",
1776 name, NULL);
1777 xmlFree(ret);
1778 return (NULL);
1779 } else {
1780 xmlSchemaTypePtr prev;
1781
1782 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1783 if (prev == NULL) {
1784 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1785 XML_ERR_INTERNAL_ERROR,
1786 "Internal error on type %s definition\n",
1787 name, NULL);
1788 xmlFree(ret);
1789 return (NULL);
1790 }
1791 ret->redef = prev->redef;
1792 prev->redef = ret;
1793 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001794 }
1795 ret->minOccurs = 1;
1796 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00001797 ret->attributeUses = NULL;
1798 ret->attributeWildcard = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001799
1800 return (ret);
1801}
1802
1803/**
1804 * xmlSchemaAddGroup:
1805 * @ctxt: a schema validation context
1806 * @schema: the schema being built
1807 * @name: the group name
1808 *
1809 * Add an XML schema Group definition
1810 *
1811 * Returns the new struture or NULL in case of error
1812 */
1813static xmlSchemaTypePtr
1814xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001815 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001816{
1817 xmlSchemaTypePtr ret = NULL;
1818 int val;
1819
1820 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1821 return (NULL);
1822
1823 if (schema->groupDecl == NULL)
1824 schema->groupDecl = xmlHashCreate(10);
1825 if (schema->groupDecl == NULL)
1826 return (NULL);
1827
1828 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1829 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001830 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001831 return (NULL);
1832 }
1833 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001834 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001835 val =
1836 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1837 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001838 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001839 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1840 XML_SCHEMAP_REDEFINED_GROUP,
1841 "Group %s already defined\n",
1842 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001843 xmlFree(ret);
1844 return (NULL);
1845 }
1846 ret->minOccurs = 1;
1847 ret->maxOccurs = 1;
1848
1849 return (ret);
1850}
1851
Daniel Veillard3646d642004-06-02 19:19:14 +00001852/**
1853 * xmlSchemaNewWildcardNs:
1854 * @ctxt: a schema validation context
1855 *
1856 * Creates a new wildcard namespace constraint.
1857 *
1858 * Returns the new struture or NULL in case of error
1859 */
1860static xmlSchemaWildcardNsPtr
1861xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
1862{
1863 xmlSchemaWildcardNsPtr ret;
1864
1865 ret = (xmlSchemaWildcardNsPtr)
1866 xmlMalloc(sizeof(xmlSchemaWildcardNs));
1867 if (ret == NULL) {
1868 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
1869 return (NULL);
1870 }
1871 ret->value = NULL;
1872 ret->next = NULL;
1873 return (ret);
1874}
1875
1876/**
1877 * xmlSchemaAddWildcard:
1878 * @ctxt: a schema validation context
1879 * @schema: the schema being built
1880 * @name: the group name
1881 *
1882 * Add an XML schema Group definition
1883 *
1884 * Returns the new struture or NULL in case of error
1885 */
1886static xmlSchemaWildcardPtr
1887xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
1888{
1889 xmlSchemaWildcardPtr ret = NULL;
1890
1891 if (ctxt == NULL)
1892 return (NULL);
1893
1894 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
1895 if (ret == NULL) {
1896 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
1897 return (NULL);
1898 }
1899 memset(ret, 0, sizeof(xmlSchemaWildcard));
1900 ret->minOccurs = 1;
1901 ret->maxOccurs = 1;
1902
1903 return (ret);
1904}
1905
Daniel Veillard4255d502002-04-16 15:50:10 +00001906/************************************************************************
1907 * *
1908 * Utilities for parsing *
1909 * *
1910 ************************************************************************/
1911
1912/**
1913 * xmlGetQNameProp:
1914 * @ctxt: a schema validation context
1915 * @node: a subtree containing XML Schema informations
1916 * @name: the attribute name
1917 * @namespace: the result namespace if any
1918 *
1919 * Extract a QName Attribute value
1920 *
1921 * Returns the NCName or NULL if not found, and also update @namespace
1922 * with the namespace URI
1923 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001924static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001925xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001926 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001927{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001928 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001929 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001930 const xmlChar *ret, *prefix;
1931 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001932
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001933 *namespace = NULL;
1934 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001935 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001936 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001937
Daniel Veillardba0153a2004-04-01 10:42:31 +00001938 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00001939 ns = xmlSearchNs(node->doc, node, 0);
1940 if (ns) {
1941 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1942 return (val);
1943 }
1944 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001945 ret = xmlSplitQName3(val, &len);
1946 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001947 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001948 }
1949 ret = xmlDictLookup(ctxt->dict, ret, -1);
1950 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001951
1952 ns = xmlSearchNs(node->doc, node, prefix);
1953 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001954 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
Daniel Veillard01fa6152004-06-29 17:04:39 +00001955 "Attribute \"%s\": the QName prefix \"%s\" is undefined\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001956 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001957 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001958 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001959 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001960 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001961}
1962
1963/**
1964 * xmlGetMaxOccurs:
1965 * @ctxt: a schema validation context
1966 * @node: a subtree containing XML Schema informations
1967 *
1968 * Get the maxOccurs property
1969 *
1970 * Returns the default if not found, or the value
1971 */
1972static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001973xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1974{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001975 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001976 int ret = 0;
1977
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001978 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001979 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001980 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001981
1982 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001983 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001984 }
1985
1986 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001987 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001988 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001989 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001990 ret = ret * 10 + (*cur - '0');
1991 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001992 }
William M. Brack76e95df2003-10-18 16:20:14 +00001993 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001994 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001995 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001996 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1997 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001998 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001999 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002000 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002001}
2002
2003/**
2004 * xmlGetMinOccurs:
2005 * @ctxt: a schema validation context
2006 * @node: a subtree containing XML Schema informations
2007 *
2008 * Get the minOccurs property
2009 *
2010 * Returns the default if not found, or the value
2011 */
2012static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002013xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2014{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002015 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00002016 int ret = 0;
2017
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002018 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00002019 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002020 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002021
2022 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00002023 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002024 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002025 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002026 ret = ret * 10 + (*cur - '0');
2027 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002028 }
William M. Brack76e95df2003-10-18 16:20:14 +00002029 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002030 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002031 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002032 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2033 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002034 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002035 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002036 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002037}
2038
2039/**
2040 * xmlGetBooleanProp:
2041 * @ctxt: a schema validation context
2042 * @node: a subtree containing XML Schema informations
2043 * @name: the attribute name
2044 * @def: the default value
2045 *
2046 * Get is a bolean property is set
2047 *
2048 * Returns the default if not found, 0 if found to be false,
2049 * 1 if found to be true
2050 */
2051static int
2052xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002053 const char *name, int def)
2054{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002055 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00002056
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002057 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002058 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002059 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00002060
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002061 if (xmlStrEqual(val, BAD_CAST "true"))
2062 def = 1;
2063 else if (xmlStrEqual(val, BAD_CAST "false"))
2064 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00002065 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002066 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
2067 "Attribute %s: the value %s is not boolean\n",
2068 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002069 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002070 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00002071}
2072
2073/************************************************************************
2074 * *
2075 * Shema extraction from an Infoset *
2076 * *
2077 ************************************************************************/
2078static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
2079 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00002080 xmlNodePtr node,
2081 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002082static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
2083 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00002084 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00002085 xmlNodePtr node,
2086 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002087static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
2088 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00002089 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002090 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002091static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
2092 xmlSchemaPtr schema,
2093 xmlNodePtr node);
2094static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
2095 xmlSchemaPtr schema,
2096 xmlNodePtr node);
2097static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
2098 ctxt,
2099 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002100 xmlNodePtr node,
2101 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002102static xmlSchemaAttributeGroupPtr
2103xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00002104 xmlSchemaPtr schema, xmlNodePtr node,
2105 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002106static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
2107 xmlSchemaPtr schema,
2108 xmlNodePtr node);
2109static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
2110 xmlSchemaPtr schema,
2111 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00002112static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002113xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
2114 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002115
2116/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002117 * xmlSchemaParseSchemaAttrValue:
2118 *
2119 * @ctxt: a schema parser context
2120 * @attr: the schema attribute being validated
2121 * @type: the built-in type to be validated against
2122 * @value: the value to be validated
2123 *
2124 * Validates a value against the given built-in type.
2125 * This one is intended to be used internally for validation
2126 * of schema attribute values during parsing of the schema.
2127 *
2128 * Returns 0 if the value is valid, a positive error code
2129 * number otherwise and -1 in case of an internal or API error.
2130 */
2131static int
2132xmlSchemaParseSchemaAttrValue(xmlSchemaParserCtxtPtr ctxt,
2133 xmlAttrPtr attr,
2134 xmlSchemaTypePtr type)
2135{
2136 const xmlChar *value;
2137 int ret;
2138
2139 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
2140 return (-1);
2141 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
2142 switch (type->builtInType) {
2143 case XML_SCHEMAS_NCNAME:
2144 ret = xmlValidateNCName(value, 1);
2145 break;
2146 case XML_SCHEMAS_QNAME:
2147 ret = xmlValidateQName(value, 1);
2148 if ((ret == 0) && (attr != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00002149 xmlChar *local = NULL;
2150 xmlChar *prefix;
2151
2152 local = xmlSplitQName2(value, &prefix);
2153 if (prefix != NULL) {
2154 xmlNsPtr ns;
2155
2156 ns = xmlSearchNs(attr->doc, (xmlNodePtr) attr, prefix);
2157 if (ns == NULL) {
2158 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
2159 XML_SCHEMAP_PREFIX_UNDEFINED,
2160 "Attribute \"%s\": the QName prefix "
2161 "\"%s\" is undefined.\n",
2162 attr->name, prefix);
2163 ret = 1;
2164 }
2165 }
2166 if (local != NULL)
2167 xmlFree(local);
2168 if (prefix != NULL)
2169 xmlFree(prefix);
2170 }
2171 break;
2172 default: {
2173 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
2174 XML_SCHEMAS_ERR_INTERNAL,
2175 "Internal error: xmlSchemaParseSchemaAttrValue, validation "
2176 "using this type in not implemented yet\"%s\".\n",
2177 type->name, NULL);
2178 return (-1);
2179 }
2180 }
2181 if (ret > 0) {
2182 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
2183 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr,
2184 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
2185 NULL, NULL, NULL,
2186 "The schema attribute \"%s\" with the value \"%s\" is not "
2187 "of built-in list simple type \"%s\".\n",
2188 attr->name, value, type->name, NULL, NULL);
2189 } else {
2190 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) {
2191 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr,
2192 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
2193 NULL, NULL, NULL,
2194 "The schema attribute \"%s\" with the value \"%s\" is not "
2195 "of built-in primitive type \"%s\".\n",
2196 attr->name, value, type->name, NULL, NULL);
2197 } else {
2198 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr,
2199 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
2200 NULL, NULL, NULL,
2201 "The schema attribute \"%s\" with the value \"%s\" is not "
2202 "of built-in atomic simple type \"%s\".\n",
2203 attr->name, value, type->name, NULL, NULL);
2204 }
2205 }
2206 }
2207 return (ret);
2208}
2209
2210/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002211 * xmlSchemaParseAttrDecls:
2212 * @ctxt: a schema validation context
2213 * @schema: the schema being built
2214 * @node: a subtree containing XML Schema informations
2215 * @type: the hosting type
2216 *
2217 * parse a XML schema attrDecls declaration corresponding to
2218 * <!ENTITY % attrDecls
2219 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
2220 */
2221static xmlNodePtr
2222xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2223 xmlNodePtr child, xmlSchemaTypePtr type)
2224{
2225 xmlSchemaAttributePtr lastattr, attr;
2226
2227 lastattr = NULL;
2228 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002229 (IS_SCHEMA(child, "attributeGroup"))) {
2230 attr = NULL;
2231 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00002232 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002233 } else if (IS_SCHEMA(child, "attributeGroup")) {
2234 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00002235 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002236 }
2237 if (attr != NULL) {
2238 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002239 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
2240 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
2241 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002242 type->attributes = attr;
2243 lastattr = attr;
2244 } else {
2245 lastattr->next = attr;
2246 lastattr = attr;
2247 }
2248 }
2249 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002250 }
2251 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002252 xmlSchemaWildcardPtr wildcard;
2253
2254 wildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
2255 if (wildcard != NULL) {
2256 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
2257 ((xmlSchemaAttributeGroupPtr) type)->attributeWildcard = wildcard;
2258 else
2259 type->attributeWildcard = wildcard;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002260 }
2261 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002262 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002263 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002264}
2265
2266/**
2267 * xmlSchemaParseAnnotation:
2268 * @ctxt: a schema validation context
2269 * @schema: the schema being built
2270 * @node: a subtree containing XML Schema informations
2271 *
2272 * parse a XML schema Attrribute declaration
2273 * *WARNING* this interface is highly subject to change
2274 *
William M. Bracke7091952004-05-11 15:09:58 +00002275 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002276 * 1 in case of success.
2277 */
2278static xmlSchemaAnnotPtr
2279xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2280 xmlNodePtr node)
2281{
2282 xmlSchemaAnnotPtr ret;
2283
2284 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2285 return (NULL);
2286 ret = xmlSchemaNewAnnot(ctxt, node);
2287
2288 return (ret);
2289}
2290
2291/**
2292 * xmlSchemaParseFacet:
2293 * @ctxt: a schema validation context
2294 * @schema: the schema being built
2295 * @node: a subtree containing XML Schema informations
2296 *
2297 * parse a XML schema Facet declaration
2298 * *WARNING* this interface is highly subject to change
2299 *
2300 * Returns the new type structure or NULL in case of error
2301 */
2302static xmlSchemaFacetPtr
2303xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002304 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002305{
2306 xmlSchemaFacetPtr facet;
2307 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002308 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00002309
2310 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2311 return (NULL);
2312
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002313 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002314 if (facet == NULL) {
2315 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
2316 return (NULL);
2317 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002318 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002319 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00002320 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002321 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
2322 "Facet %s has no value\n", node->name, NULL);
2323 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00002324 return (NULL);
2325 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002326 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002327 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002328 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002329 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002330 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002331 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002332 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002333 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002334 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002335 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002336 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002337 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002338 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002339 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002340 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002341 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002342 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002343 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002344 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002345 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002346 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002347 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
2348 } else if (IS_SCHEMA(node, "minLength")) {
2349 facet->type = XML_SCHEMA_FACET_MINLENGTH;
2350 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002351 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
2352 "Unknown facet type %s\n", node->name, NULL);
2353 xmlSchemaFreeFacet(facet);
2354 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002355 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002356 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002357 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00002358 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
2359 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
2360 const xmlChar *fixed;
2361
2362 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
2363 if (fixed != NULL) {
2364 if (xmlStrEqual(fixed, BAD_CAST "true"))
2365 facet->fixed = 1;
2366 }
2367 }
2368
Daniel Veillard4255d502002-04-16 15:50:10 +00002369 child = node->children;
2370
2371 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002372 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2373 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002374 }
2375 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002376 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
2377 "Facet %s has unexpected child content\n",
2378 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002379 }
2380 return (facet);
2381}
2382
2383/**
2384 * xmlSchemaParseAny:
2385 * @ctxt: a schema validation context
2386 * @schema: the schema being built
2387 * @node: a subtree containing XML Schema informations
2388 *
2389 * parse a XML schema Any declaration
2390 * *WARNING* this interface is highly subject to change
2391 *
2392 * Returns the new type structure or NULL in case of error
2393 */
2394static xmlSchemaTypePtr
2395xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2396 xmlNodePtr node)
2397{
2398 xmlSchemaTypePtr type;
2399 xmlNodePtr child = NULL;
2400 xmlChar name[30];
2401
2402 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2403 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002404 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002405 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002406 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002407 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002408 type->node = node;
2409 type->type = XML_SCHEMA_TYPE_ANY;
2410 child = node->children;
2411 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2412 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2413
2414 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002415 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2416 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002417 }
2418 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002419 xmlSchemaPErr2(ctxt, node, child,
2420 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
2421 "Sequence %s has unexpected content\n", type->name,
2422 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002423 }
2424
2425 return (type);
2426}
2427
2428/**
2429 * xmlSchemaParseNotation:
2430 * @ctxt: a schema validation context
2431 * @schema: the schema being built
2432 * @node: a subtree containing XML Schema informations
2433 *
2434 * parse a XML schema Notation declaration
2435 *
2436 * Returns the new structure or NULL in case of error
2437 */
2438static xmlSchemaNotationPtr
2439xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002440 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002441{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002442 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002443 xmlSchemaNotationPtr ret;
2444 xmlNodePtr child = NULL;
2445
2446 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2447 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002448 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002449 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002450 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
2451 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002452 return (NULL);
2453 }
2454 ret = xmlSchemaAddNotation(ctxt, schema, name);
2455 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002456 return (NULL);
2457 }
2458 child = node->children;
2459 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002460 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2461 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002462 }
2463 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002464 xmlSchemaPErr2(ctxt, node, child,
2465 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
2466 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002467 }
2468
2469 return (ret);
2470}
2471
2472/**
2473 * xmlSchemaParseAnyAttribute:
2474 * @ctxt: a schema validation context
2475 * @schema: the schema being built
2476 * @node: a subtree containing XML Schema informations
2477 *
2478 * parse a XML schema AnyAttrribute declaration
2479 * *WARNING* this interface is highly subject to change
2480 *
2481 * Returns an attribute def structure or NULL
2482 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002483static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002484xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
2485 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002486{
Daniel Veillard3646d642004-06-02 19:19:14 +00002487 const xmlChar *processContents, *nsConstraint, *end, *cur, *dictMember;
2488 xmlChar *member;
2489 xmlSchemaWildcardPtr ret;
2490 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002491 xmlNodePtr child = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002492
2493 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2494 return (NULL);
2495
Daniel Veillard3646d642004-06-02 19:19:14 +00002496 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00002497 if (ret == NULL) {
2498 return (NULL);
2499 }
William M. Bracke7091952004-05-11 15:09:58 +00002500 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002501 ret->id = xmlSchemaGetProp(ctxt, node, "id");
2502 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002503 if ((processContents == NULL)
2504 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00002505 ret->processContents = XML_SCHEMAS_ANY_STRICT;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002506 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00002507 ret->processContents = XML_SCHEMAS_ANY_SKIP;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002508 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00002509 ret->processContents = XML_SCHEMAS_ANY_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00002510 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00002511 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002512 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
William M. Bracke7091952004-05-11 15:09:58 +00002513 "anyAttribute has unexpected content "
2514 "for processContents: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002515 processContents, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002516 ret->processContents = XML_SCHEMAS_ANY_STRICT;
Daniel Veillard3646d642004-06-02 19:19:14 +00002517 }
2518 /*
2519 * Build the namespace constraints.
2520 */
2521 nsConstraint = xmlSchemaGetProp(ctxt, node, "namespace");
William M. Brack803812b2004-06-03 02:11:24 +00002522 if ((nsConstraint == NULL) || (xmlStrEqual(nsConstraint, BAD_CAST "##any")))
Daniel Veillard3646d642004-06-02 19:19:14 +00002523 ret->any = 1;
William M. Brack803812b2004-06-03 02:11:24 +00002524 else if (xmlStrEqual(nsConstraint, BAD_CAST "##other")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002525 ret->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
2526 if (ret->negNsSet == NULL) {
2527 xmlSchemaFreeWildcard(ret);
2528 return (NULL);
2529 }
2530 ret->negNsSet->value = schema->targetNamespace;
2531 } else {
2532 cur = nsConstraint;
2533 do {
2534 while (IS_BLANK_CH(*cur))
2535 cur++;
2536 end = cur;
2537 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
2538 end++;
2539 if (end == cur)
2540 break;
2541 member = xmlStrndup(cur, end - cur);
William M. Brack803812b2004-06-03 02:11:24 +00002542 if ((xmlStrEqual(member, BAD_CAST "##other")) ||
2543 (xmlStrEqual(member, BAD_CAST "##any"))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002544 xmlSchemaPErr(ctxt, ret->node, XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
2545 "The namespace constraint of an anyAttribute "
2546 "is a set and must not contain \"%s\"\n",
2547 member, NULL);
2548 } else {
2549 /*
2550 * TODO: Validate the value (anyURI).
2551 */
William M. Brack803812b2004-06-03 02:11:24 +00002552 if (xmlStrEqual(member, BAD_CAST "##targetNamespace")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002553 dictMember = schema->targetNamespace;
William M. Brack803812b2004-06-03 02:11:24 +00002554 } else if (xmlStrEqual(member, BAD_CAST "##local")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002555 dictMember = NULL;
2556 } else
2557 dictMember = xmlDictLookup(ctxt->dict, member, -1);
2558 /*
2559 * Avoid dublicate namespaces.
2560 */
2561 tmp = ret->nsSet;
2562 while (tmp != NULL) {
2563 if (dictMember == tmp->value)
2564 break;
2565 tmp = tmp->next;
2566 }
2567 if (tmp == NULL) {
2568 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
2569 if (tmp == NULL) {
2570 xmlFree(member);
2571 xmlSchemaFreeWildcard(ret);
2572 return (NULL);
2573 }
2574 tmp->value = dictMember;
2575 tmp->next = NULL;
2576 if (ret->nsSet == NULL)
2577 ret->nsSet = tmp;
2578 else
2579 lastNs->next = tmp;
2580 lastNs = tmp;
2581 }
2582
2583 }
2584 xmlFree(member);
2585 cur = end;
2586 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00002587 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002588
2589 child = node->children;
2590 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002591 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2592 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002593 }
2594 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002595 xmlSchemaPErr2(ctxt, node, child,
2596 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
Daniel Veillard3646d642004-06-02 19:19:14 +00002597 "anyAttribute has unexpected content\n",
2598 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002599 }
2600
2601 return (ret);
2602}
2603
2604
2605/**
2606 * xmlSchemaParseAttribute:
2607 * @ctxt: a schema validation context
2608 * @schema: the schema being built
2609 * @node: a subtree containing XML Schema informations
2610 *
2611 * parse a XML schema Attrribute declaration
2612 * *WARNING* this interface is highly subject to change
2613 *
William M. Bracke7091952004-05-11 15:09:58 +00002614 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002615 */
2616static xmlSchemaAttributePtr
2617xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002618 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002619{
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002620 const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal;
Daniel Veillard4255d502002-04-16 15:50:10 +00002621 xmlSchemaAttributePtr ret;
2622 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002623 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002624 int hasRefType = 0;
William M. Bracke7091952004-05-11 15:09:58 +00002625
2626 /*
2627 * Note that the w3c spec assumes the schema to be validated with schema
2628 * for schemas beforehand.
2629 *
2630 * 3.2.3 Constraints on XML Representations of Attribute Declarations
2631 *
2632 * TODO: Complete implementation of:
2633 * 3.2.6 Schema Component Constraint: Attribute Declaration Properties
2634 * Correct
2635 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002636
2637 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2638 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002639
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002640 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002641 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002642 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002643 /* 3.2.3 : 3.1
2644 * One of ref or name must be present, but not both
2645 */
2646 if (ref == NULL) {
2647 xmlSchemaPErr(ctxt, node,
2648 XML_SCHEMAP_ATTR_NONAME_NOREF,
2649 "Attribute declaration has no \"name\" or \"ref\"\n",
2650 NULL, NULL);
2651 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002652 }
William M. Bracke7091952004-05-11 15:09:58 +00002653 hasRefType = 1;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002654 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2655 name = (const xmlChar *) buf;
2656 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002657 if (!topLevel) {
2658 /* 3.2.3 : 3.2
2659 * If ref is present, then all of <simpleType>,
2660 * form and type must be absent.
2661 */
2662 if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2663 xmlSchemaPErr(ctxt, node,
2664 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2665 "Attribute declaration %s has \"ref\", thus "
2666 "\"form\" must be absent\n", name, NULL);
2667 }
2668 if (xmlSchemaGetProp(ctxt, node, "type") != NULL) {
2669 xmlSchemaPErr(ctxt, node,
2670 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2671 "Attribute declaration %s has \"ref\", thus "
2672 "\"type\" must be absent\n", name, NULL);
2673 }
2674 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002675 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002676 const xmlChar *ns = NULL;
2677 /* 3.2.3 : 3.1
2678 * One of ref or name must be present, but not both
2679 */
2680 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2681 xmlSchemaPErr(ctxt, node,
2682 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
Daniel Veillard3646d642004-06-02 19:19:14 +00002683 "Attribute declaration \"%s\" has both, \"name\" and "
2684 "\"ref\"\n", name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002685 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002686
William M. Bracke7091952004-05-11 15:09:58 +00002687 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2688 /* Evaluate the target namespace */
2689 if (schema->targetNamespace != NULL) {
2690 if (topLevel) {
2691 ns = schema->targetNamespace;
2692 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2693 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2694 BAD_CAST "qualified")) {
2695 ns = schema->targetNamespace;
2696 }
2697 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2698 ns = schema->targetNamespace;
2699 }
2700 }
2701 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns);
Daniel Veillard3646d642004-06-02 19:19:14 +00002702 if (ret == NULL)
2703 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002704 /* 3.2.6 Schema Component Constraint: xmlns Not Allowed */
2705 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2706 xmlSchemaPErr(ctxt, node,
2707 XML_SCHEMAP_INVALID_ATTR_NAME,
2708 "The name of an attribute declaration must not match "
2709 "\"xmlns\".\n", NULL, NULL);
2710 }
2711
2712 /* 3.2.6 Schema Component Constraint: xsi: Not Allowed */
2713 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
2714 xmlSchemaPErr(ctxt, node,
2715 XML_SCHEMAP_INVALID_ATTR_NAME,
2716 "The target namespace of an attribute declaration, "
2717 "must not match \"http://www.w3.org/2001/"
2718 "XMLSchema-instance\"", NULL, NULL);
2719 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002720 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002721 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002722 return (NULL);
2723 }
William M. Bracke7091952004-05-11 15:09:58 +00002724 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Daniel Veillard3646d642004-06-02 19:19:14 +00002725 if (topLevel)
2726 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
William M. Bracke7091952004-05-11 15:09:58 +00002727
2728 /* Handle the "use" attribute. */
2729 attrVal = xmlSchemaGetProp(ctxt, node, "use");
2730 if (attrVal != NULL) {
2731 if (xmlStrEqual(attrVal, BAD_CAST "optional"))
2732 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2733 else if (xmlStrEqual(attrVal, BAD_CAST "prohibited"))
2734 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
2735 else if (xmlStrEqual(attrVal, BAD_CAST "required"))
2736 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
2737 else
2738 xmlSchemaPErr(ctxt, node,
2739 XML_SCHEMAP_INVALID_ATTR_USE,
2740 "Attribute declaration %s has an invalid "
2741 "value for \"use\"\n", name, NULL);
2742 } else
2743 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002744
William M. Bracke7091952004-05-11 15:09:58 +00002745
2746 if (xmlSchemaGetProp(ctxt, node, "default") != NULL) {
2747 /* 3.2.3 : 1
2748 * default and fixed must not both be present.
2749 */
2750 if (xmlSchemaGetProp(ctxt, node, "fixed") != NULL) {
2751 xmlSchemaPErr(ctxt, node,
2752 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2753 "Attribute declaration has both, \"default\" "
2754 "and \"fixed\"\n", NULL, NULL);
2755 }
2756 /* 3.2.3 : 2
2757 * If default and use are both present, use must have
2758 * the actual value optional.
2759 */
2760 if (ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) {
2761 xmlSchemaPErr(ctxt, node,
2762 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2763 "Attribute declaration has \"default\" but "
2764 "\"use\" is not \"optional\"\n", NULL, NULL);
2765 }
2766 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002767
Daniel Veillard4255d502002-04-16 15:50:10 +00002768 ret->ref = ref;
2769 ret->refNs = refNs;
William M. Bracke7091952004-05-11 15:09:58 +00002770 /*
2771 * The setting of XML_SCHEMAS_ATTR_NSDEFAULT is not needed anymore,
2772 * since the target namespace was already evaluated and took
2773 * attributeFormDefault into account.
2774 */
2775 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002776 if ((ret->targetNamespace != NULL) &&
2777 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2778 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2779 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
William M. Bracke7091952004-05-11 15:09:58 +00002780 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002781 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
William M. Bracke7091952004-05-11 15:09:58 +00002782 if (ret->typeName != NULL)
2783 hasRefType = 1;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002784 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002785 child = node->children;
2786 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002787 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2788 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002789 }
2790 if (IS_SCHEMA(child, "simpleType")) {
William M. Bracke7091952004-05-11 15:09:58 +00002791 if (hasRefType) {
2792 /* 3.2.3 : 4
2793 * type and <simpleType> must not both be present.
2794 *
2795 * TODO: XML_SCHEMAP_INVALID_ATTR_COMBINATION seems not to be
2796 * a proper error type here.
2797 */
2798 xmlSchemaPErr2(ctxt, node, child,
2799 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2800 "Attribute declaration %s has both (\"ref\" or "
2801 "\"type\") and <simpleType>\n", name, NULL);
2802 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00002803 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002804 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002805 }
2806 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002807 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2808 "attribute %s has unexpected content\n", name,
2809 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002810 }
2811
2812 return (ret);
2813}
2814
2815/**
2816 * xmlSchemaParseAttributeGroup:
2817 * @ctxt: a schema validation context
2818 * @schema: the schema being built
2819 * @node: a subtree containing XML Schema informations
2820 *
2821 * parse a XML schema Attribute Group declaration
2822 * *WARNING* this interface is highly subject to change
2823 *
2824 * Returns the attribute group or NULL in case of error.
2825 */
2826static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002827xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00002828 xmlSchemaPtr schema, xmlNodePtr node,
2829 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002830{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002831 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002832 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00002833 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002834 const xmlChar *oldcontainer;
2835 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002836
2837 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2838 return (NULL);
2839 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002840 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002841 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002842 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2843 if (ref == NULL) {
2844 xmlSchemaPErr2(ctxt, node, child,
2845 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2846 "AttributeGroup has no name nor ref\n", NULL,
2847 NULL);
2848 return (NULL);
2849 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002850 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2851 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002852 if (name == NULL) {
2853 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2854 return (NULL);
2855 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002856 }
2857 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2858 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002859 return (NULL);
2860 }
2861 ret->ref = ref;
2862 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002863 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00002864 if (topLevel)
2865 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002866 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002867 child = node->children;
2868 ctxt->container = name;
2869 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002870 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2871 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002872 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002873 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
2874 /* Seems that this can be removed. */
2875 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00002876 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002877 (IS_SCHEMA(child, "attributeGroup"))) {
2878 attr = NULL;
2879 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00002880 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002881 } else if (IS_SCHEMA(child, "attributeGroup")) {
2882 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00002883 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002884 }
2885 if (attr != NULL) {
2886 if (last == NULL) {
2887 ret->attributes = attr;
2888 last = attr;
2889 } else {
2890 last->next = attr;
2891 last = attr;
2892 }
2893 }
2894 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002895 }
2896 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002897 TODO
2898 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002899 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002900 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002901 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002902 xmlSchemaPErr2(ctxt, node, child,
2903 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2904 "attribute group %s has unexpected content\n", name,
2905 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002906 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002907 ctxt->container = oldcontainer;
2908 return (ret);
2909}
2910
2911/**
2912 * xmlSchemaParseElement:
2913 * @ctxt: a schema validation context
2914 * @schema: the schema being built
2915 * @node: a subtree containing XML Schema informations
2916 *
2917 * parse a XML schema Element declaration
2918 * *WARNING* this interface is highly subject to change
2919 *
William M. Bracke7091952004-05-11 15:09:58 +00002920 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002921 */
2922static xmlSchemaElementPtr
2923xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00002924 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002925{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002926 const xmlChar *name, *fixed;
2927 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002928 xmlSchemaElementPtr ret;
2929 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002930 const xmlChar *oldcontainer;
2931 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002932 xmlAttrPtr attr;
2933
2934 /* 3.3.3 Constraints on XML Representations of Element Declarations */
2935 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002936
2937 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2938 return (NULL);
2939 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002940 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002941 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002942 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002943 /* 3.3.3 : 2.1
2944 * One of ref or name must be present, but not both
2945 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002946 if (ref == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00002947 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002948 XML_SCHEMAP_ELEM_NONAME_NOREF,
Daniel Veillard3646d642004-06-02 19:19:14 +00002949 "Element declaration has no name nor ref\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002950 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002951 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002952
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002953 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2954 name = (const xmlChar *) buf;
2955 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2956 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002957 const xmlChar *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002958
William M. Bracke7091952004-05-11 15:09:58 +00002959 /* Evaluate the target namespace */
2960 if (schema->targetNamespace != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002961 if (topLevel) {
William M. Bracke7091952004-05-11 15:09:58 +00002962 ns = schema->targetNamespace;
2963 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2964 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2965 BAD_CAST "qualified")) {
2966 ns = schema->targetNamespace;
2967 }
2968 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2969 ns = schema->targetNamespace;
2970 }
2971 }
2972 /*local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2973 ret = xmlSchemaAddElement(ctxt, schema, name, ns);
2974 /* 3.3.3 : 2.1
2975 * One of ref or name must be present, but not both
2976 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002977 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00002978 xmlSchemaPErr(ctxt, node,
2979 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2980 "Element declaration has both, \"name\" and "
2981 "\"ref\"\n", NULL, NULL);
2982 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002983 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002984 if (ret != NULL)
2985 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002986 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002987 return (NULL);
2988 }
2989 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2990 ret->ref = ref;
2991 ret->refNs = refNs;
2992 if (ref != NULL)
2993 ret->flags |= XML_SCHEMAS_ELEM_REF;
William M. Bracke7091952004-05-11 15:09:58 +00002994
2995 /* 3.3.3 : 2.2 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002996 if ((!topLevel) && (ref != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00002997 attr = node->properties;
2998 while (attr != NULL) {
2999 if ((attr->ns == NULL) &&
3000 (!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
3001 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
3002 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
3003 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
3004
3005 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
3006 "Element declaration %s: only minOccurs, maxOccurs "
3007 "and id are allowed in addition to ref\n",
3008 ret->name, NULL);
3009 }
3010 attr = attr->next;
3011 }
3012 }
3013
Daniel Veillard3646d642004-06-02 19:19:14 +00003014 if (topLevel) {
3015 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003016 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Daniel Veillard3646d642004-06-02 19:19:14 +00003017 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003018 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
3019 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
3020 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Daniel Veillard3646d642004-06-02 19:19:14 +00003021 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillard4255d502002-04-16 15:50:10 +00003022 ctxt->container = name;
3023
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003024 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003025 ret->namedType =
William M. Bracke7091952004-05-11 15:09:58 +00003026 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003027 ret->substGroup =
3028 xmlGetQNameProp(ctxt, node, "substitutionGroup",
3029 &(ret->substGroupNs));
Daniel Veillard3646d642004-06-02 19:19:14 +00003030 if ((ret->substGroup != NULL) && (!topLevel)) {
William M. Bracke7091952004-05-11 15:09:58 +00003031 /* 3.3.6 : 3 */
3032 /*
3033 * TODO: This seems to be redundant, since the schema for schemas
3034 * already prohibits the use of the "substitutionGroup" attribute
3035 * in local element declarations.
3036 */
3037 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
3038 "Element declaration %s: substitutionGroup is allowed "
3039 "on top-level declarations only\n", ret->name, NULL);
3040
3041 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003042 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00003043 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
3044 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003045
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003046 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00003047 if ((ret->value != NULL) && (fixed != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00003048 /* 3.3.3 : 1
3049 * default and fixed must not both be present.
3050 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003051 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
3052 "Element %s has both default and fixed\n",
3053 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003054 } else if (fixed != NULL) {
3055 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003056 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00003057 }
3058
3059 child = node->children;
3060 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003061 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3062 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003063 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003064
William M. Bracke7091952004-05-11 15:09:58 +00003065 if (ref != NULL) {
3066 /* 3.3.3 (2.2) */
3067 while (child != NULL) {
3068 if ((IS_SCHEMA(child, "complexType")) ||
3069 (IS_SCHEMA(child, "simpleType")) ||
3070 (IS_SCHEMA(child, "unique")) ||
3071 (IS_SCHEMA(child, "key")) ||
3072 (IS_SCHEMA(child, "keyref"))) {
3073
3074 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_REF_AND_CONTENT,
3075 "Element declaration %s: only annotation is "
3076 "allowed as content in addition to ref\n",
3077 ret->name, NULL);
3078 } else {
3079 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
3080 "element %s has unexpected content\n", name, NULL);
3081 }
3082 child = child->next;
3083 }
3084 } else {
3085 if (IS_SCHEMA(child, "complexType")) {
3086 /* 3.3.3 : 3
3087 * type and either <simpleType> or <complexType> are mutually
3088 * exclusive
3089 */
3090 if (ret->namedType != NULL) {
3091 xmlSchemaPErr2(ctxt, node, child,
3092 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
3093 "Element declaration %s has both \"type\" "
3094 "and a local complex type\n",
3095 ret->name, NULL);
3096 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00003097 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00003098 child = child->next;
3099 } else if (IS_SCHEMA(child, "simpleType")) {
3100 /* 3.3.3 : 3
3101 * type and either <simpleType> or <complexType> are
3102 * mutually exclusive
3103 */
3104 if (ret->namedType != NULL) {
3105 xmlSchemaPErr2(ctxt, node, child,
3106 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
3107 "Element declaration %s has both \"type\" "
3108 "and a local simple type\n",
3109 ret->name, NULL);
3110 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00003111 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00003112 child = child->next;
3113 }
3114
3115 while ((IS_SCHEMA(child, "unique")) ||
3116 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
3117 TODO child = child->next;
3118 }
3119 if (child != NULL) {
3120 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
3121 "element %s has unexpected content\n", name, NULL);
3122 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003123 }
3124
3125 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003126 return (ret);
3127}
3128
3129/**
3130 * xmlSchemaParseUnion:
3131 * @ctxt: a schema validation context
3132 * @schema: the schema being built
3133 * @node: a subtree containing XML Schema informations
3134 *
3135 * parse a XML schema Union definition
3136 * *WARNING* this interface is highly subject to change
3137 *
William M. Bracke7091952004-05-11 15:09:58 +00003138 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003139 * 1 in case of success.
3140 */
3141static xmlSchemaTypePtr
3142xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003143 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003144{
3145 xmlSchemaTypePtr type, subtype, last = NULL;
3146 xmlNodePtr child = NULL;
3147 xmlChar name[30];
3148
3149 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3150 return (NULL);
3151
3152
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003153 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00003154 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003155 if (type == NULL)
3156 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00003157 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00003158 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003159 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003160 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00003161
3162 child = node->children;
3163 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003164 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3165 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003166 }
3167 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003168 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00003169 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003170 if (subtype != NULL) {
3171 if (last == NULL) {
3172 type->subtypes = subtype;
3173 last = subtype;
3174 } else {
3175 last->next = subtype;
3176 last = subtype;
3177 }
3178 last->next = NULL;
3179 }
3180 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003181 }
3182 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003183 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
3184 "Union %s has unexpected content\n", type->name,
3185 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003186 }
3187 return (type);
3188}
3189
3190/**
3191 * xmlSchemaParseList:
3192 * @ctxt: a schema validation context
3193 * @schema: the schema being built
3194 * @node: a subtree containing XML Schema informations
3195 *
3196 * parse a XML schema List definition
3197 * *WARNING* this interface is highly subject to change
3198 *
William M. Bracke7091952004-05-11 15:09:58 +00003199 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 * 1 in case of success.
3201 */
3202static xmlSchemaTypePtr
3203xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003204 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003205{
3206 xmlSchemaTypePtr type, subtype;
3207 xmlNodePtr child = NULL;
3208 xmlChar name[30];
Daniel Veillard01fa6152004-06-29 17:04:39 +00003209 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003210
3211 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3212 return (NULL);
3213
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003214 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003215 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003216 if (type == NULL)
3217 return (NULL);
3218 type->node = node;
3219 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003220 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003221
3222 child = node->children;
3223 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003224 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3225 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003226 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003227 /*
3228 * Check type of "itemType".
3229 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003230 attr = xmlSchemaGetPropNode(node, BAD_CAST "itemType");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003231 if (attr != NULL) {
3232 type->base = xmlGetQNameProp(ctxt, node, "itemType", &(type->baseNs));
3233 xmlSchemaParseSchemaAttrValue(ctxt, attr,
3234 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
3235
3236 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003237 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003238 if (IS_SCHEMA(child, "simpleType")) {
3239 subtype = (xmlSchemaTypePtr)
3240 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
3241 type->subtypes = subtype;
3242 /*
3243 * This is a hack to save the information that a local
3244 * simple type was defined.
3245 */
3246 type->baseType = subtype;
3247 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003248 }
3249 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003250 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
3251 "List %s has unexpected content\n", type->name,
3252 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003253 }
3254 return (type);
3255}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003256
Daniel Veillard4255d502002-04-16 15:50:10 +00003257/**
3258 * xmlSchemaParseSimpleType:
3259 * @ctxt: a schema validation context
3260 * @schema: the schema being built
3261 * @node: a subtree containing XML Schema informations
3262 *
3263 * parse a XML schema Simple Type definition
3264 * *WARNING* this interface is highly subject to change
3265 *
William M. Bracke7091952004-05-11 15:09:58 +00003266 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003267 * 1 in case of success.
3268 */
3269static xmlSchemaTypePtr
3270xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003271 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003272{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003273 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00003274 xmlNodePtr child = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003275 const xmlChar *propVal;
Daniel Veillard4255d502002-04-16 15:50:10 +00003276
3277 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3278 return (NULL);
3279
Daniel Veillard01fa6152004-06-29 17:04:39 +00003280 ctxtType = ctxt->ctxtType;
3281 propVal = xmlSchemaGetProp(ctxt, node, "name");
3282 if (propVal == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003283 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003284
William M. Bracke7091952004-05-11 15:09:58 +00003285 snprintf(buf, 99, "simpleType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003286 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00003287 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00003288 if (!topLevel) {
3289 xmlSchemaPErr(ctxt, node,
3290 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3291 "The attribute \"name\" is not allowed on a local "
3292 "simpleType definition\n",
3293 propVal, NULL);
3294 return (NULL);
3295 }
3296 /*
3297 * "name" has to be of type NCName.
3298 * TODO: Actually this should be validated by the schema for schemas.
3299 */
3300 if (xmlSchemaParseSchemaAttrValue(ctxt,
3301 xmlSchemaGetPropNode(node, BAD_CAST "name"),
3302 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME)) != 0)
3303 return (NULL);
3304 type = xmlSchemaAddType(ctxt, schema, propVal, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003305 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003306 if (type == NULL)
3307 return (NULL);
3308 type->node = node;
3309 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillard3646d642004-06-02 19:19:14 +00003310 if (topLevel)
3311 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003312 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003313 propVal = xmlSchemaGetProp(ctxt, node, "final");
3314 if (propVal == NULL) {
3315 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
3316 } else {
3317 if (xmlStrEqual(propVal, BAD_CAST "#all")) {
3318 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
3319 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
3320 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
3321 } else {
3322 const xmlChar *end, *cur = propVal;
3323 xmlChar *item;
3324
3325 do {
3326 while (IS_BLANK_CH(*cur))
3327 cur++;
3328 end = cur;
3329 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
3330 end++;
3331 if (end == cur)
3332 break;
3333 item = xmlStrndup(cur, end - cur);
3334 if (xmlStrEqual(item, BAD_CAST "restriction")) {
3335 if ((type->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) == 0)
3336 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
3337 } else if (xmlStrEqual(item, BAD_CAST "list")) {
3338 if ((type->flags & XML_SCHEMAS_TYPE_FINAL_LIST) == 0)
3339 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
3340 } else if (xmlStrEqual(item, BAD_CAST "union")) {
3341 if ((type->flags & XML_SCHEMAS_TYPE_FINAL_UNION) == 0)
3342 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
3343 } else {
3344 xmlSchemaPErr(ctxt, node,
3345 XML_SCHEMAS_ERR_INTERNAL,
3346 "The attribute \"final\" of type \"%s\" "
3347 "has an invalid value\n",
3348 type->name, NULL);
3349 }
3350 if (item != NULL)
3351 xmlFree(item);
3352 cur = end;
3353 } while (*cur != 0);
3354 }
3355 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003356 child = node->children;
3357 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003358 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3359 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003360 }
3361 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003362 ctxt->ctxtType = type;
3363 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00003364 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003365 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003366 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003367 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003368 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003369 subtype = (xmlSchemaTypePtr)
3370 xmlSchemaParseList(ctxt, schema, child);
3371 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003372 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003373 subtype = (xmlSchemaTypePtr)
3374 xmlSchemaParseUnion(ctxt, schema, child);
3375 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003376 }
3377 type->subtypes = subtype;
3378 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003379 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillard01fa6152004-06-29 17:04:39 +00003380 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
3381 "SimpleType \"%s\" has unexpected content\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003382 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003383 } else {
3384 if (subtype == NULL) {
3385 xmlSchemaPErr2(ctxt, node, child,
3386 XML_SCHEMAP_S4S_ELEM_MISSING,
3387 "SimpleType \"%s\" must have one of <restriction> or "
3388 "<list> or <union> as a child\n",
3389 type->name, NULL);
3390 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003391 }
3392
Daniel Veillard01fa6152004-06-29 17:04:39 +00003393 ctxt->ctxtType = ctxtType;
3394
Daniel Veillard4255d502002-04-16 15:50:10 +00003395 return (type);
3396}
3397
3398
3399/**
3400 * xmlSchemaParseGroup:
3401 * @ctxt: a schema validation context
3402 * @schema: the schema being built
3403 * @node: a subtree containing XML Schema informations
3404 *
3405 * parse a XML schema Group definition
3406 * *WARNING* this interface is highly subject to change
3407 *
William M. Bracke7091952004-05-11 15:09:58 +00003408 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003409 * 1 in case of success.
3410 */
3411static xmlSchemaTypePtr
3412xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003413 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003414{
3415 xmlSchemaTypePtr type, subtype;
3416 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003417 const xmlChar *name;
3418 const xmlChar *ref = NULL, *refNs = NULL;
3419 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003420
3421 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3422 return (NULL);
3423
3424
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003425 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003426 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003427 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
3428 if (ref == NULL) {
3429 xmlSchemaPErr2(ctxt, node, child,
3430 XML_SCHEMAP_GROUP_NONAME_NOREF,
3431 "Group has no name nor ref\n", NULL, NULL);
3432 return (NULL);
3433 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003434 if (refNs == NULL)
3435 refNs = schema->targetNamespace;
3436 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
3437 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00003438 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003439 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003440 if (type == NULL)
3441 return (NULL);
3442 type->node = node;
3443 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00003444 if (topLevel)
3445 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003446 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003447 type->ref = ref;
3448 type->refNs = refNs;
3449 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3450 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3451
3452 child = node->children;
3453 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003454 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3455 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003456 }
3457 subtype = NULL;
3458 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003459 subtype = (xmlSchemaTypePtr)
3460 xmlSchemaParseAll(ctxt, schema, child);
3461 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003462 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003463 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3464 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003465 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003466 subtype = (xmlSchemaTypePtr)
3467 xmlSchemaParseSequence(ctxt, schema, child);
3468 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003469 }
3470 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003471 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003472 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003473 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
3474 "Group %s has unexpected content\n", type->name,
3475 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003476 }
3477
3478 return (type);
3479}
3480
3481/**
3482 * xmlSchemaParseAll:
3483 * @ctxt: a schema validation context
3484 * @schema: the schema being built
3485 * @node: a subtree containing XML Schema informations
3486 *
3487 * parse a XML schema All definition
3488 * *WARNING* this interface is highly subject to change
3489 *
William M. Bracke7091952004-05-11 15:09:58 +00003490 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003491 * 1 in case of success.
3492 */
3493static xmlSchemaTypePtr
3494xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003495 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003496{
3497 xmlSchemaTypePtr type, subtype, last = NULL;
3498 xmlNodePtr child = NULL;
3499 xmlChar name[30];
3500
3501 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3502 return (NULL);
3503
3504
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003505 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003506 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003507 if (type == NULL)
3508 return (NULL);
3509 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00003510 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003511 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003512 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00003513 if (type->minOccurs > 1)
3514 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
3515 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003516 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00003517 if (type->maxOccurs > 1)
3518 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
3519 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003520
3521 child = node->children;
3522 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003523 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3524 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003525 }
3526 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003527 subtype = (xmlSchemaTypePtr)
3528 xmlSchemaParseElement(ctxt, schema, child, 0);
3529 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00003530 if (subtype->minOccurs > 1)
3531 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
3532 "invalid value for minOccurs (must be 0 or 1)\n",
3533 NULL, NULL);
3534 if (subtype->maxOccurs > 1)
3535 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
3536 "invalid value for maxOccurs (must be 0 or 1)\n",
3537 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003538 if (last == NULL) {
3539 type->subtypes = subtype;
3540 last = subtype;
3541 } else {
3542 last->next = subtype;
3543 last = subtype;
3544 }
3545 last->next = NULL;
3546 }
3547 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003548 }
3549 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003550 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
3551 "All %s has unexpected content\n", type->name,
3552 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003553 }
3554
3555 return (type);
3556}
3557
3558/**
Daniel Veillard1d913862003-11-21 00:28:39 +00003559 * xmlSchemaImportSchema
3560 *
3561 * @ctxt: a schema validation context
3562 * @schemaLocation: an URI defining where to find the imported schema
3563 *
3564 * import a XML schema
3565 * *WARNING* this interface is highly subject to change
3566 *
3567 * Returns -1 in case of error and 1 in case of success.
3568 */
3569static xmlSchemaImportPtr
3570xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
3571 const xmlChar *schemaLocation)
3572{
3573 xmlSchemaImportPtr import;
3574 xmlSchemaParserCtxtPtr newctxt;
3575
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003576 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00003577 if (newctxt == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003578 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00003579 NULL);
3580 return (NULL);
3581 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003582 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
3583 /* Keep the same dictionnary for parsing, really */
3584 xmlDictReference(ctxt->dict);
3585 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003586 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003587 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
3588
Daniel Veillard1d913862003-11-21 00:28:39 +00003589 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
3590 ctxt->userData);
3591
3592 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
3593 if (import == NULL) {
3594 xmlSchemaPErrMemory(NULL, "allocating imported schema",
3595 NULL);
3596 xmlSchemaFreeParserCtxt(newctxt);
3597 return (NULL);
3598 }
3599
3600 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003601 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00003602 import->schema = xmlSchemaParse(newctxt);
3603
3604 if (import->schema == NULL) {
3605 /* FIXME use another error enum here ? */
3606 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
3607 "failed to import schema at location %s\n",
3608 schemaLocation, NULL);
3609
3610 xmlSchemaFreeParserCtxt(newctxt);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00003611 if (import->schemaLocation != NULL)
3612 xmlFree((xmlChar *)import->schemaLocation);
Daniel Veillard1d913862003-11-21 00:28:39 +00003613 xmlFree(import);
3614 return NULL;
3615 }
3616
3617 xmlSchemaFreeParserCtxt(newctxt);
3618 return import;
3619}
3620
3621
3622/**
Daniel Veillard5a872412002-05-22 06:40:27 +00003623 * xmlSchemaParseImport:
3624 * @ctxt: a schema validation context
3625 * @schema: the schema being built
3626 * @node: a subtree containing XML Schema informations
3627 *
3628 * parse a XML schema Import definition
3629 * *WARNING* this interface is highly subject to change
3630 *
William M. Bracke7091952004-05-11 15:09:58 +00003631 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard5a872412002-05-22 06:40:27 +00003632 * 1 in case of success.
3633 */
3634static int
3635xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003636 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00003637{
3638 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00003639 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003640 const xmlChar *namespace;
3641 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00003642 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00003643 xmlURIPtr check;
3644
Daniel Veillard1d913862003-11-21 00:28:39 +00003645
Daniel Veillard5a872412002-05-22 06:40:27 +00003646 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3647 return (-1);
3648
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003649 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00003650 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003651 check = xmlParseURI((const char *) namespace);
3652 if (check == NULL) {
3653 xmlSchemaPErr2(ctxt, node, child,
3654 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
3655 "Import namespace attribute is not an URI: %s\n",
3656 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003657 return (-1);
3658 } else {
3659 xmlFreeURI(check);
3660 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003661 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003662 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00003663 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003664 xmlChar *base = NULL;
3665 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003666 check = xmlParseURI((const char *) schemaLocation);
3667 if (check == NULL) {
3668 xmlSchemaPErr2(ctxt, node, child,
3669 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
3670 "Import schemaLocation attribute is not an URI: %s\n",
3671 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003672 return (-1);
3673 } else {
3674 xmlFreeURI(check);
3675 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003676 base = xmlNodeGetBase(node->doc, node);
3677 if (base == NULL) {
3678 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3679 } else {
3680 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003681 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00003682 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003683 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003684 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3685 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00003686 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003687 }
3688 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003689 schema->schemasImports = xmlHashCreate(10);
3690 if (schema->schemasImports == NULL) {
3691 xmlSchemaPErr2(ctxt, node, child,
3692 XML_SCHEMAP_FAILED_BUILD_IMPORT,
3693 "Internal: failed to build import table\n",
3694 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003695 return (-1);
3696 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003697 }
3698 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003699 import = xmlHashLookup(schema->schemasImports,
3700 XML_SCHEMAS_DEFAULT_NAMESPACE);
3701 if (import != NULL)
3702 previous = import->schemaLocation;
3703 else
3704 previous = NULL;
3705
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003706 if (schemaLocation != NULL) {
3707 if (previous != NULL) {
3708 if (!xmlStrEqual(schemaLocation, previous)) {
3709 xmlSchemaPErr2(ctxt, node, child,
3710 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003711 "Redefining import for default namespace "
3712 "with a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003713 schemaLocation, NULL);
3714 }
3715 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003716 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3717 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003718 return (-1);
3719 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003720 xmlHashAddEntry(schema->schemasImports,
3721 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00003722 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003723 }
3724 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003725 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003726 import = xmlHashLookup(schema->schemasImports, namespace);
3727 if (import != NULL)
3728 previous = import->schemaLocation;
3729 else
3730 previous = NULL;
3731
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003732 if (schemaLocation != NULL) {
3733 if (previous != NULL) {
3734 if (!xmlStrEqual(schemaLocation, previous)) {
3735 xmlSchemaPErr2(ctxt, node, child,
3736 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003737 "Redefining import for namespace %s with "
3738 "a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003739 namespace, schemaLocation);
3740 }
3741 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003742 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3743 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003744 return (-1);
3745 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003746 if (!xmlStrEqual(import->schema->targetNamespace, namespace)) {
3747 if (namespace == NULL) {
3748 if (import->schema->targetNamespace != NULL) {
William M. Brack767265d2004-06-03 10:50:29 +00003749 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_2,
Daniel Veillard3646d642004-06-02 19:19:14 +00003750 "There is no namespace attribute on the <import> "
3751 "element information item, so the imported document "
3752 "must have no targetNamespace attribute.\n",
3753 NULL, NULL);
3754 }
3755 } else {
3756 if (import->schema->targetNamespace != NULL) {
William M. Brack767265d2004-06-03 10:50:29 +00003757 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_1,
Daniel Veillard3646d642004-06-02 19:19:14 +00003758 "The namespace attribute \"%s\" of an <import> "
3759 "element information item must be identical to the "
3760 "targetNamespace attribute \"%s\" of the "
3761 "imported document.\n",
3762 namespace, import->schema->targetNamespace);
3763 } else {
William M. Brack767265d2004-06-03 10:50:29 +00003764 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_1,
Daniel Veillard3646d642004-06-02 19:19:14 +00003765 "The namespace attribute on the <import> "
3766 "element information item, requires the imported "
3767 "document to have a targetNamespace attribute "
3768 "with the value \"%s\".\n",
3769 namespace, NULL);
3770 }
3771 }
3772 xmlSchemaFreeImport(import);
3773 return (-1);
3774 }
3775
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003776 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00003777 namespace, import);
Daniel Veillard3646d642004-06-02 19:19:14 +00003778
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003779 }
3780 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003781 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003782
3783 child = node->children;
3784 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003785 /*
3786 * the annotations here are simply discarded ...
3787 */
3788 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00003789 }
3790 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003791 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
3792 "Import has unexpected content\n", NULL, NULL);
3793 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003794 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003795 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003796}
3797
3798/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003799 * xmlSchemaCleanupDoc:
3800 * @ctxt: a schema validation context
3801 * @node: the root of the document.
3802 *
3803 * removes unwanted nodes in a schemas document tree
3804 */
3805static void
3806xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
3807{
3808 xmlNodePtr delete, cur;
3809
3810 if ((ctxt == NULL) || (root == NULL)) return;
3811
3812 /*
3813 * Remove all the blank text nodes
3814 */
3815 delete = NULL;
3816 cur = root;
3817 while (cur != NULL) {
3818 if (delete != NULL) {
3819 xmlUnlinkNode(delete);
3820 xmlFreeNode(delete);
3821 delete = NULL;
3822 }
3823 if (cur->type == XML_TEXT_NODE) {
3824 if (IS_BLANK_NODE(cur)) {
3825 if (xmlNodeGetSpacePreserve(cur) != 1) {
3826 delete = cur;
3827 }
3828 }
3829 } else if ((cur->type != XML_ELEMENT_NODE) &&
3830 (cur->type != XML_CDATA_SECTION_NODE)) {
3831 delete = cur;
3832 goto skip_children;
3833 }
3834
3835 /*
3836 * Skip to next node
3837 */
3838 if (cur->children != NULL) {
3839 if ((cur->children->type != XML_ENTITY_DECL) &&
3840 (cur->children->type != XML_ENTITY_REF_NODE) &&
3841 (cur->children->type != XML_ENTITY_NODE)) {
3842 cur = cur->children;
3843 continue;
3844 }
3845 }
3846 skip_children:
3847 if (cur->next != NULL) {
3848 cur = cur->next;
3849 continue;
3850 }
3851
3852 do {
3853 cur = cur->parent;
3854 if (cur == NULL)
3855 break;
3856 if (cur == root) {
3857 cur = NULL;
3858 break;
3859 }
3860 if (cur->next != NULL) {
3861 cur = cur->next;
3862 break;
3863 }
3864 } while (cur != NULL);
3865 }
3866 if (delete != NULL) {
3867 xmlUnlinkNode(delete);
3868 xmlFreeNode(delete);
3869 delete = NULL;
3870 }
3871}
3872
3873/**
3874 * xmlSchemaParseSchemaTopLevel:
3875 * @ctxt: a schema validation context
3876 * @schema: the schemas
3877 * @nodes: the list of top level nodes
3878 *
3879 * Returns the internal XML Schema structure built from the resource or
3880 * NULL in case of error
3881 */
3882static void
3883xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
3884 xmlSchemaPtr schema, xmlNodePtr nodes)
3885{
3886 xmlNodePtr child;
3887 xmlSchemaAnnotPtr annot;
3888
3889 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
3890 return;
3891
3892 child = nodes;
3893 while ((IS_SCHEMA(child, "include")) ||
3894 (IS_SCHEMA(child, "import")) ||
3895 (IS_SCHEMA(child, "redefine")) ||
3896 (IS_SCHEMA(child, "annotation"))) {
3897 if (IS_SCHEMA(child, "annotation")) {
3898 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3899 if (schema->annot == NULL)
3900 schema->annot = annot;
3901 else
3902 xmlSchemaFreeAnnot(annot);
3903 } else if (IS_SCHEMA(child, "import")) {
3904 xmlSchemaParseImport(ctxt, schema, child);
3905 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003906 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003907 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003908 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003909 } else if (IS_SCHEMA(child, "redefine")) {
3910 TODO
3911 }
3912 child = child->next;
3913 }
3914 while (child != NULL) {
3915 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003916 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003917 child = child->next;
3918 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003919 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003920 child = child->next;
3921 } else if (IS_SCHEMA(child, "element")) {
3922 xmlSchemaParseElement(ctxt, schema, child, 1);
3923 child = child->next;
3924 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003925 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003926 child = child->next;
3927 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003928 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003929 child = child->next;
3930 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003931 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003932 child = child->next;
3933 } else if (IS_SCHEMA(child, "notation")) {
3934 xmlSchemaParseNotation(ctxt, schema, child);
3935 child = child->next;
3936 } else {
3937 xmlSchemaPErr2(ctxt, NULL, child,
3938 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
3939 "Schemas: unexpected element %s here \n",
3940 child->name, NULL);
3941 child = child->next;
3942 }
3943 while (IS_SCHEMA(child, "annotation")) {
3944 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3945 if (schema->annot == NULL)
3946 schema->annot = annot;
3947 else
3948 xmlSchemaFreeAnnot(annot);
3949 child = child->next;
3950 }
3951 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003952 ctxt->parentItem = NULL;
3953 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003954}
3955
3956/**
3957 * xmlSchemaParseInclude:
3958 * @ctxt: a schema validation context
3959 * @schema: the schema being built
3960 * @node: a subtree containing XML Schema informations
3961 *
3962 * parse a XML schema Include definition
3963 *
William M. Bracke7091952004-05-11 15:09:58 +00003964 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003965 * 1 in case of success.
3966 */
3967static int
3968xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3969 xmlNodePtr node)
3970{
3971 xmlNodePtr child = NULL;
3972 const xmlChar *schemaLocation;
3973 xmlURIPtr check;
3974 xmlDocPtr doc;
3975 xmlNodePtr root;
3976 xmlSchemaIncludePtr include;
3977
3978
3979 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3980 return (-1);
3981
3982 /*
3983 * Preliminary step, extract the URI-Reference for the include and
3984 * make an URI from the base.
3985 */
3986 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
3987 if (schemaLocation != NULL) {
3988 xmlChar *base = NULL;
3989 xmlChar *URI = NULL;
3990 check = xmlParseURI((const char *) schemaLocation);
3991 if (check == NULL) {
3992 xmlSchemaPErr2(ctxt, node, child,
3993 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3994 "Include schemaLocation attribute is not an URI: %s\n",
3995 schemaLocation, NULL);
3996 return (-1);
3997 } else {
3998 xmlFreeURI(check);
3999 }
4000 base = xmlNodeGetBase(node->doc, node);
4001 if (base == NULL) {
4002 URI = xmlBuildURI(schemaLocation, node->doc->URL);
4003 } else {
4004 URI = xmlBuildURI(schemaLocation, base);
4005 xmlFree(base);
4006 }
4007 if (URI != NULL) {
4008 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
4009 xmlFree(URI);
4010 }
4011 } else {
4012 xmlSchemaPErr2(ctxt, node, child,
4013 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
4014 "Include schemaLocation attribute missing\n",
4015 NULL, NULL);
4016 return (-1);
4017 }
4018
4019 child = node->children;
4020 while (IS_SCHEMA(child, "annotation")) {
4021 /*
4022 * the annotations here are simply discarded ...
4023 */
4024 child = child->next;
4025 }
4026 if (child != NULL) {
4027 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
4028 "Include has unexpected content\n", NULL, NULL);
4029 return (-1);
4030 }
4031
4032 /*
4033 * First step is to parse the input document into an DOM/Infoset
4034 */
4035 doc = xmlReadFile((const char *) schemaLocation, NULL,
4036 SCHEMAS_PARSE_OPTIONS);
4037 if (doc == NULL) {
4038 xmlSchemaPErr(ctxt, NULL,
4039 XML_SCHEMAP_FAILED_LOAD,
4040 "xmlSchemaParse: could not load %s\n",
4041 ctxt->URL, NULL);
4042 return(-1);
4043 }
4044
4045 /*
4046 * Then extract the root of the schema
4047 */
4048 root = xmlDocGetRootElement(doc);
4049 if (root == NULL) {
4050 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4051 XML_SCHEMAP_NOROOT,
4052 "schemas %s has no root", schemaLocation, NULL);
4053 xmlFreeDoc(doc);
4054 return (-1);
4055 }
4056
4057 /*
4058 * Remove all the blank text nodes
4059 */
4060 xmlSchemaCleanupDoc(ctxt, root);
4061
4062 /*
4063 * Check the schemas top level element
4064 */
4065 if (!IS_SCHEMA(root, "schema")) {
4066 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4067 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillard01fa6152004-06-29 17:04:39 +00004068 "File %s is not a schema", schemaLocation, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004069 xmlFreeDoc(doc);
4070 return (-1);
4071 }
4072
4073 /*
4074 * register the include
4075 */
4076 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
4077 if (include == NULL) {
4078 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
4079 xmlFreeDoc(doc);
4080 return (-1);
4081 }
4082
4083 memset(include, 0, sizeof(xmlSchemaInclude));
4084 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
4085 include->doc = doc;
4086 include->next = schema->includes;
4087 schema->includes = include;
4088
4089
4090 /*
4091 * parse the declarations in the included file like if they
4092 * were in the original file.
4093 */
4094 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
4095
4096 return (1);
4097}
4098
4099/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004100 * xmlSchemaParseChoice:
4101 * @ctxt: a schema validation context
4102 * @schema: the schema being built
4103 * @node: a subtree containing XML Schema informations
4104 *
4105 * parse a XML schema Choice definition
4106 * *WARNING* this interface is highly subject to change
4107 *
William M. Bracke7091952004-05-11 15:09:58 +00004108 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004109 * 1 in case of success.
4110 */
4111static xmlSchemaTypePtr
4112xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004113 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004114{
4115 xmlSchemaTypePtr type, subtype, last = NULL;
4116 xmlNodePtr child = NULL;
4117 xmlChar name[30];
4118
4119 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4120 return (NULL);
4121
4122
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004123 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004124 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004125 if (type == NULL)
4126 return (NULL);
4127 type->node = node;
4128 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004129 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004130 type->minOccurs = xmlGetMinOccurs(ctxt, node);
4131 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
4132
4133 child = node->children;
4134 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004135 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4136 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004137 }
4138 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004139 (IS_SCHEMA(child, "group")) ||
4140 (IS_SCHEMA(child, "any")) ||
4141 (IS_SCHEMA(child, "choice")) ||
4142 (IS_SCHEMA(child, "sequence"))) {
4143 subtype = NULL;
4144 if (IS_SCHEMA(child, "element")) {
4145 subtype = (xmlSchemaTypePtr)
4146 xmlSchemaParseElement(ctxt, schema, child, 0);
4147 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004148 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004149 } else if (IS_SCHEMA(child, "any")) {
4150 subtype = xmlSchemaParseAny(ctxt, schema, child);
4151 } else if (IS_SCHEMA(child, "sequence")) {
4152 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4153 } else if (IS_SCHEMA(child, "choice")) {
4154 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4155 }
4156 if (subtype != NULL) {
4157 if (last == NULL) {
4158 type->subtypes = subtype;
4159 last = subtype;
4160 } else {
4161 last->next = subtype;
4162 last = subtype;
4163 }
4164 last->next = NULL;
4165 }
4166 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004167 }
4168 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004169 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
4170 "Choice %s has unexpected content\n", type->name,
4171 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004172 }
4173
4174 return (type);
4175}
4176
4177/**
4178 * xmlSchemaParseSequence:
4179 * @ctxt: a schema validation context
4180 * @schema: the schema being built
4181 * @node: a subtree containing XML Schema informations
4182 *
4183 * parse a XML schema Sequence definition
4184 * *WARNING* this interface is highly subject to change
4185 *
William M. Bracke7091952004-05-11 15:09:58 +00004186 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004187 * 1 in case of success.
4188 */
4189static xmlSchemaTypePtr
4190xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004191 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004192{
4193 xmlSchemaTypePtr type, subtype, last = NULL;
4194 xmlNodePtr child = NULL;
4195 xmlChar name[30];
4196
4197 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4198 return (NULL);
4199
4200
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004201 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004202 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004203 if (type == NULL)
4204 return (NULL);
4205 type->node = node;
4206 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004207 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004208 type->minOccurs = xmlGetMinOccurs(ctxt, node);
4209 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
4210
4211 child = node->children;
4212 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004213 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4214 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004215 }
4216 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004217 (IS_SCHEMA(child, "group")) ||
4218 (IS_SCHEMA(child, "any")) ||
4219 (IS_SCHEMA(child, "choice")) ||
4220 (IS_SCHEMA(child, "sequence"))) {
4221 subtype = NULL;
4222 if (IS_SCHEMA(child, "element")) {
4223 subtype = (xmlSchemaTypePtr)
4224 xmlSchemaParseElement(ctxt, schema, child, 0);
4225 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004226 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004227 } else if (IS_SCHEMA(child, "any")) {
4228 subtype = xmlSchemaParseAny(ctxt, schema, child);
4229 } else if (IS_SCHEMA(child, "choice")) {
4230 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4231 } else if (IS_SCHEMA(child, "sequence")) {
4232 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4233 }
4234 if (subtype != NULL) {
4235 if (last == NULL) {
4236 type->subtypes = subtype;
4237 last = subtype;
4238 } else {
4239 last->next = subtype;
4240 last = subtype;
4241 }
4242 last->next = NULL;
4243 }
4244 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004245 }
4246 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004247 xmlSchemaPErr2(ctxt, node, child,
4248 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4249 "Sequence %s has unexpected content\n", type->name,
4250 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004251 }
4252
4253 return (type);
4254}
4255
4256/**
4257 * xmlSchemaParseRestriction:
4258 * @ctxt: a schema validation context
4259 * @schema: the schema being built
4260 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00004261 *
4262 * parse a XML schema Restriction definition
4263 * *WARNING* this interface is highly subject to change
4264 *
4265 * Returns the type definition or NULL in case of error
4266 */
4267static xmlSchemaTypePtr
4268xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004269 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004270{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004271 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004272 xmlNodePtr child = NULL;
4273 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004274 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00004275
4276 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4277 return (NULL);
4278
4279 oldcontainer = ctxt->container;
4280
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004281 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004282 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004283 if (type == NULL)
4284 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004285 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00004286 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004287 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004288 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00004289 if ((type->base == NULL) &&
4290 (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004291 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillard01fa6152004-06-29 17:04:39 +00004292 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
4293 "Restriction \"%s\" must have a \"base\" attribute.\n",
4294 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004295 }
4296 ctxt->container = name;
4297
4298 child = node->children;
4299 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004300 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4301 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004302 }
4303 subtype = NULL;
4304
Daniel Veillard01fa6152004-06-29 17:04:39 +00004305 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
4306 if (IS_SCHEMA(child, "all")) {
4307 subtype = (xmlSchemaTypePtr)
4308 xmlSchemaParseAll(ctxt, schema, child);
4309 child = child->next;
4310 type->subtypes = subtype;
4311 } else if (IS_SCHEMA(child, "choice")) {
4312 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4313 child = child->next;
4314 type->subtypes = subtype;
4315 } else if (IS_SCHEMA(child, "sequence")) {
4316 subtype = (xmlSchemaTypePtr)
4317 xmlSchemaParseSequence(ctxt, schema, child);
4318 child = child->next;
4319 type->subtypes = subtype;
4320 } else if (IS_SCHEMA(child, "group")) {
4321 subtype = (xmlSchemaTypePtr)
4322 xmlSchemaParseGroup(ctxt, schema, child, 0);
4323 child = child->next;
4324 type->subtypes = subtype;
4325 }
4326 } else if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
4327 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
4328 xmlSchemaFacetPtr facet, lastfacet = NULL;
4329
4330 if (IS_SCHEMA(child, "simpleType")) {
4331 subtype = (xmlSchemaTypePtr)
4332 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4333 /*
4334 * For the simple type this serves as the base type.
4335 */
4336 type->baseType = subtype;
4337 /*
4338 * For the complex type this serves as information for the
4339 * definition of the content type.
4340 * Additionally this is a hack for the simple type, to save
4341 * the information that a local simple type was defined; thus
4342 * allowing to check: src-restriction-base-or-simpleType.
4343 */
4344 type->subtypes = subtype;
4345 child = child->next;
4346 }
4347 /*
4348 * Add the facets to the parent simpleType/complexType.
4349 */
4350 while ((IS_SCHEMA(child, "minInclusive")) ||
4351 (IS_SCHEMA(child, "minExclusive")) ||
4352 (IS_SCHEMA(child, "maxInclusive")) ||
4353 (IS_SCHEMA(child, "maxExclusive")) ||
4354 (IS_SCHEMA(child, "totalDigits")) ||
4355 (IS_SCHEMA(child, "fractionDigits")) ||
4356 (IS_SCHEMA(child, "pattern")) ||
4357 (IS_SCHEMA(child, "enumeration")) ||
4358 (IS_SCHEMA(child, "whiteSpace")) ||
4359 (IS_SCHEMA(child, "length")) ||
4360 (IS_SCHEMA(child, "maxLength")) ||
4361 (IS_SCHEMA(child, "minLength"))) {
4362 facet = xmlSchemaParseFacet(ctxt, schema, child);
4363 if (facet != NULL) {
4364 if (lastfacet == NULL)
4365 ctxt->ctxtType->facets = facet;
4366 else
4367 lastfacet->next = facet;
4368 lastfacet = facet;
4369 lastfacet->next = NULL;
4370 }
4371 child = child->next;
4372 }
4373 /*
4374 * Create links for derivation and validation.
4375 */
4376 if (lastfacet != NULL) {
4377 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
4378
4379 facet = ctxt->ctxtType->facets;
4380 do {
4381 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
4382 if (facetLink == NULL) {
4383 xmlSchemaPErrMemory(ctxt, "allocation a facet link", NULL);
4384 xmlFree(facetLink);
4385 return (NULL);
4386 }
4387 facetLink->facet = facet;
4388 facetLink->next = NULL;
4389 if (lastFacetLink == NULL)
4390 ctxt->ctxtType->facetSet = facetLink;
4391 else
4392 lastFacetLink->next = facetLink;
4393 lastFacetLink = facetLink;
4394 facet = facet->next;
4395 } while (facet != NULL);
4396 }
4397 }
4398 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)
4399 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004400 if (child != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00004401 xmlSchemaPErr2(ctxt, node, child,
4402 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
4403 "Restriction \"%s\" has unexpected content.\n",
4404 type->name, NULL);
4405 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004406 ctxt->container = oldcontainer;
4407 return (type);
4408}
4409
4410/**
4411 * xmlSchemaParseExtension:
4412 * @ctxt: a schema validation context
4413 * @schema: the schema being built
4414 * @node: a subtree containing XML Schema informations
4415 *
4416 * parse a XML schema Extension definition
4417 * *WARNING* this interface is highly subject to change
4418 *
4419 * Returns the type definition or NULL in case of error
4420 */
4421static xmlSchemaTypePtr
4422xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004423 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004424{
4425 xmlSchemaTypePtr type, subtype;
4426 xmlNodePtr child = NULL;
4427 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004428 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00004429
4430 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4431 return (NULL);
4432
4433 oldcontainer = ctxt->container;
4434
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004435 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004436 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004437 if (type == NULL)
4438 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004439 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00004440 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004441 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004442 ctxt->container = name;
4443
4444 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
4445 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004446 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
4447 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004448 }
4449 child = node->children;
4450 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004451 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4452 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004453 }
4454 subtype = NULL;
4455
4456 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004457 subtype = xmlSchemaParseAll(ctxt, schema, child);
4458 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004459 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004460 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4461 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004462 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004463 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4464 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004465 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004466 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004467 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004468 }
4469 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004470 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004471 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
4472 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004473 xmlSchemaPErr2(ctxt, node, child,
4474 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
4475 "Extension %s has unexpected content\n", type->name,
4476 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004477 }
4478 ctxt->container = oldcontainer;
4479 return (type);
4480}
4481
4482/**
4483 * xmlSchemaParseSimpleContent:
4484 * @ctxt: a schema validation context
4485 * @schema: the schema being built
4486 * @node: a subtree containing XML Schema informations
4487 *
4488 * parse a XML schema SimpleContent definition
4489 * *WARNING* this interface is highly subject to change
4490 *
4491 * Returns the type definition or NULL in case of error
4492 */
4493static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004494xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
4495 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004496{
4497 xmlSchemaTypePtr type, subtype;
4498 xmlNodePtr child = NULL;
4499 xmlChar name[30];
4500
4501 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4502 return (NULL);
4503
William M. Bracke7091952004-05-11 15:09:58 +00004504 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004505 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004506 if (type == NULL)
4507 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004508 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00004509 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004510 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004511
4512 child = node->children;
4513 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004514 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4515 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004516 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004517 ctxt->parentItem = type;
4518 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004519 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004520 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004521 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004522 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004523 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004524 subtype = (xmlSchemaTypePtr)
4525 xmlSchemaParseExtension(ctxt, schema, child);
4526 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004527 }
4528 type->subtypes = subtype;
4529 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004530 xmlSchemaPErr2(ctxt, node, child,
4531 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
4532 "SimpleContent %s has unexpected content\n",
4533 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004534 }
4535 return (type);
4536}
4537
4538/**
4539 * xmlSchemaParseComplexContent:
4540 * @ctxt: a schema validation context
4541 * @schema: the schema being built
4542 * @node: a subtree containing XML Schema informations
4543 *
4544 * parse a XML schema ComplexContent definition
4545 * *WARNING* this interface is highly subject to change
4546 *
4547 * Returns the type definition or NULL in case of error
4548 */
4549static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004550xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
4551 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004552{
4553 xmlSchemaTypePtr type, subtype;
4554 xmlNodePtr child = NULL;
4555 xmlChar name[30];
4556
4557 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4558 return (NULL);
4559
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004560 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004561 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004562 if (type == NULL)
4563 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004564 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004565 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004566 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004567
4568 child = node->children;
4569 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004570 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4571 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004572 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004573 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004574 subtype = NULL;
4575 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004576 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004577 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004578 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004579 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004580 subtype = (xmlSchemaTypePtr)
4581 xmlSchemaParseExtension(ctxt, schema, child);
4582 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004583 }
4584 type->subtypes = subtype;
4585 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004586 xmlSchemaPErr2(ctxt, node, child,
4587 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
4588 "ComplexContent %s has unexpected content\n",
4589 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004590 }
4591 return (type);
4592}
4593
4594/**
4595 * xmlSchemaParseComplexType:
4596 * @ctxt: a schema validation context
4597 * @schema: the schema being built
4598 * @node: a subtree containing XML Schema informations
4599 *
4600 * parse a XML schema Complex Type definition
4601 * *WARNING* this interface is highly subject to change
4602 *
4603 * Returns the type definition or NULL in case of error
4604 */
4605static xmlSchemaTypePtr
4606xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004607 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004608{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004609 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004610 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004611 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00004612 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004613 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00004614
4615 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4616 return (NULL);
4617
Daniel Veillard01fa6152004-06-29 17:04:39 +00004618 ctxtType = ctxt->ctxtType;
4619
Daniel Veillard4255d502002-04-16 15:50:10 +00004620 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004621 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004622 if (name == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00004623 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004624 name = (const xmlChar *)buf;
4625 type = xmlSchemaAddType(ctxt, schema, name, NULL);
4626 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004627
William M. Bracke7091952004-05-11 15:09:58 +00004628 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
4629 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004630 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004631 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004632 return (NULL);
4633 }
William M. Bracke7091952004-05-11 15:09:58 +00004634 if (xmlGetBooleanProp(ctxt, node, "mixed", 0))
4635 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004636
Daniel Veillard4255d502002-04-16 15:50:10 +00004637 type->node = node;
4638 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillard3646d642004-06-02 19:19:14 +00004639 if (topLevel)
4640 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004641 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004642 ctxt->container = name;
4643
4644 child = node->children;
4645 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004646 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4647 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004648 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004649 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004650 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00004651 /* 3.4.3 : 2.2
4652 * Specifying mixed='true' when the <simpleContent>
4653 * alternative is chosen has no effect
4654 */
4655 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
4656 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004657 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
4658 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004659 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004660 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
4661 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004662 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004663 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004664
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004665 if (IS_SCHEMA(child, "all")) {
4666 subtype = xmlSchemaParseAll(ctxt, schema, child);
4667 child = child->next;
4668 } else if (IS_SCHEMA(child, "choice")) {
4669 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4670 child = child->next;
4671 } else if (IS_SCHEMA(child, "sequence")) {
4672 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4673 child = child->next;
4674 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004675 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004676 child = child->next;
4677 }
4678 if (subtype != NULL)
4679 type->subtypes = subtype;
4680 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004681 }
4682 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004683 xmlSchemaPErr2(ctxt, node, child,
4684 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
4685 "ComplexType %s has unexpected content\n",
4686 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004687 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004688 if (type->attributeWildcard != NULL)
4689 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillard4255d502002-04-16 15:50:10 +00004690 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004691 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004692 return (type);
4693}
4694
Daniel Veillard4255d502002-04-16 15:50:10 +00004695/**
4696 * xmlSchemaParseSchema:
4697 * @ctxt: a schema validation context
4698 * @node: a subtree containing XML Schema informations
4699 *
4700 * parse a XML schema definition from a node set
4701 * *WARNING* this interface is highly subject to change
4702 *
4703 * Returns the internal XML Schema structure built from the resource or
4704 * NULL in case of error
4705 */
4706static xmlSchemaPtr
4707xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4708{
4709 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004710 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004711 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004712 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004713
4714 if ((ctxt == NULL) || (node == NULL))
4715 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004716
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004717 nberrors = ctxt->nberrors;
4718 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004719 if (IS_SCHEMA(node, "schema")) {
4720 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004721 if (schema == NULL)
4722 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004723 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
4724 if (val != NULL) {
4725 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
4726 } else {
4727 schema->targetNamespace = NULL;
4728 }
4729 schema->id = xmlSchemaGetProp(ctxt, node, "id");
4730 schema->version = xmlSchemaGetProp(ctxt, node, "version");
4731 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004732 if (val != NULL) {
4733 if (xmlStrEqual(val, BAD_CAST "qualified"))
4734 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
4735 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4736 xmlSchemaPErr2(ctxt, node, child,
4737 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
4738 "Invalid value %s for elementFormDefault\n",
4739 val, NULL);
4740 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004741 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00004742 /* Removed, since the default value for elementFormDefault
4743 * is "unqualified".
4744 */
4745 /* schema->flags |= XML_SCHEMAS_QUALIF_ELEM; */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004746 }
4747 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004748 if (val != NULL) {
4749 if (xmlStrEqual(val, BAD_CAST "qualified"))
4750 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
4751 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4752 xmlSchemaPErr2(ctxt, node, child,
4753 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
4754 "Invalid value %s for attributeFormDefault\n",
4755 val, NULL);
4756 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004757 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004758
Daniel Veillard01fa6152004-06-29 17:04:39 +00004759 val = xmlSchemaGetProp(ctxt, node, "finalDefault");
4760 if (val != NULL) {
4761 if (xmlStrEqual(val, BAD_CAST "#all")) {
4762 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
4763 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
4764 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_LIST;
4765 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_UNION;
4766 } else {
4767 const xmlChar *end, *cur = val;
4768 xmlChar *item;
4769
4770 do {
4771 while (IS_BLANK_CH(*cur))
4772 cur++;
4773 end = cur;
4774 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4775 end++;
4776 if (end == cur)
4777 break;
4778 item = xmlStrndup(cur, end - cur);
4779 if (xmlStrEqual(item, BAD_CAST "extension")) {
4780 if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) == 0)
4781 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
4782 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
4783 if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) == 0)
4784 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
4785 } else if (xmlStrEqual(item, BAD_CAST "list")) {
4786 if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST) == 0)
4787 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_LIST;
4788 } else if (xmlStrEqual(item, BAD_CAST "union")) {
4789 if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION) == 0)
4790 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_UNION;
4791 } else {
4792 xmlSchemaPErr(ctxt, node,
4793 XML_SCHEMAS_ERR_INTERNAL,
4794 "Invalid value for the attribute \"finalDefault\".\n",
4795 NULL, NULL);
4796 }
4797 if (item != NULL)
4798 xmlFree(item);
4799 cur = end;
4800 } while (*cur != 0);
4801 }
4802 }
4803
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004804 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
4805 } else {
4806 xmlDocPtr doc;
4807
4808 doc = node->doc;
4809
4810 if ((doc != NULL) && (doc->URL != NULL)) {
4811 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4812 XML_SCHEMAP_NOT_SCHEMA,
4813 "File %s is not a schemas", doc->URL, NULL);
4814 } else {
4815 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4816 XML_SCHEMAP_NOT_SCHEMA,
4817 "File is not a schemas", NULL, NULL);
4818 }
4819 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004820 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004821 if (ctxt->nberrors != 0) {
4822 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004823 xmlSchemaFree(schema);
4824 schema = NULL;
4825 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004826 }
4827 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004828#ifdef DEBUG
4829 if (schema == NULL)
4830 xmlGenericError(xmlGenericErrorContext,
4831 "xmlSchemaParse() failed\n");
4832#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004833 return (schema);
4834}
4835
4836/************************************************************************
4837 * *
4838 * Validating using Schemas *
4839 * *
4840 ************************************************************************/
4841
4842/************************************************************************
4843 * *
4844 * Reading/Writing Schemas *
4845 * *
4846 ************************************************************************/
4847
4848/**
4849 * xmlSchemaNewParserCtxt:
4850 * @URL: the location of the schema
4851 *
4852 * Create an XML Schemas parse context for that file/resource expected
4853 * to contain an XML Schemas file.
4854 *
4855 * Returns the parser context or NULL in case of error
4856 */
4857xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004858xmlSchemaNewParserCtxt(const char *URL)
4859{
Daniel Veillard4255d502002-04-16 15:50:10 +00004860 xmlSchemaParserCtxtPtr ret;
4861
4862 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004863 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004864
4865 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4866 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004867 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4868 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004869 return (NULL);
4870 }
4871 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004872 ret->dict = xmlDictCreate();
4873 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004874 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004875 return (ret);
4876}
4877
4878/**
Daniel Veillard6045c902002-10-09 21:13:59 +00004879 * xmlSchemaNewMemParserCtxt:
4880 * @buffer: a pointer to a char array containing the schemas
4881 * @size: the size of the array
4882 *
4883 * Create an XML Schemas parse context for that memory buffer expected
4884 * to contain an XML Schemas file.
4885 *
4886 * Returns the parser context or NULL in case of error
4887 */
4888xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004889xmlSchemaNewMemParserCtxt(const char *buffer, int size)
4890{
Daniel Veillard6045c902002-10-09 21:13:59 +00004891 xmlSchemaParserCtxtPtr ret;
4892
4893 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004894 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00004895
4896 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4897 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004898 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
4899 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00004900 return (NULL);
4901 }
4902 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4903 ret->buffer = buffer;
4904 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00004905 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00004906 return (ret);
4907}
4908
4909/**
Daniel Veillard9d751502003-10-29 13:21:47 +00004910 * xmlSchemaNewDocParserCtxt:
4911 * @doc: a preparsed document tree
4912 *
4913 * Create an XML Schemas parse context for that document.
4914 * NB. The document may be modified during the parsing process.
4915 *
4916 * Returns the parser context or NULL in case of error
4917 */
4918xmlSchemaParserCtxtPtr
4919xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
4920{
4921 xmlSchemaParserCtxtPtr ret;
4922
4923 if (doc == NULL)
4924 return (NULL);
4925
4926 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
4927 if (ret == NULL) {
4928 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
4929 NULL);
4930 return (NULL);
4931 }
4932 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
4933 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00004934 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00004935 /* The application has responsibility for the document */
4936 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00004937
4938 return (ret);
4939}
4940
4941/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004942 * xmlSchemaFreeParserCtxt:
4943 * @ctxt: the schema parser context
4944 *
4945 * Free the resources associated to the schema parser context
4946 */
4947void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004948xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
4949{
Daniel Veillard4255d502002-04-16 15:50:10 +00004950 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004951 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004952 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004953 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004954 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004955 xmlFree(ctxt);
4956}
4957
4958/************************************************************************
4959 * *
4960 * Building the content models *
4961 * *
4962 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004963
Daniel Veillard4255d502002-04-16 15:50:10 +00004964/**
4965 * xmlSchemaBuildAContentModel:
4966 * @type: the schema type definition
4967 * @ctxt: the schema parser context
4968 * @name: the element name whose content is being built
4969 *
4970 * Generate the automata sequence needed for that type
4971 */
4972static void
4973xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004974 xmlSchemaParserCtxtPtr ctxt,
4975 const xmlChar * name)
4976{
Daniel Veillard4255d502002-04-16 15:50:10 +00004977 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004978 xmlGenericError(xmlGenericErrorContext,
4979 "Found unexpected type = NULL in %s content model\n",
4980 name);
4981 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004982 }
4983 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004984 case XML_SCHEMA_TYPE_ANY:
4985 /* TODO : handle the namespace too */
4986 /* TODO : make that a specific transition type */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004987 /* Daniel says: use xmlAutomataNewTransition2 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004988 TODO ctxt->state =
4989 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
4990 BAD_CAST "*", NULL);
4991 break;
4992 case XML_SCHEMA_TYPE_ELEMENT:{
4993 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00004994
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004995 /* TODO : handle the namespace too */
4996 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00004997
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004998 if (elem->maxOccurs >= UNBOUNDED) {
4999 if (elem->minOccurs > 1) {
5000 xmlAutomataStatePtr tmp;
5001 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00005002
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005003 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
5004 oldstate,
5005 NULL);
5006 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00005007
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005008 counter = xmlAutomataNewCounter(ctxt->am,
5009 elem->minOccurs -
5010 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00005011
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005012 if (elem->refDecl != NULL) {
5013 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
5014 elem->refDecl,
5015 ctxt,
5016 elem->refDecl->
5017 name);
5018 } else {
5019 ctxt->state =
5020 xmlAutomataNewTransition(ctxt->am,
5021 ctxt->state, NULL,
5022 elem->name, type);
5023 }
5024 tmp = ctxt->state;
5025 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
5026 counter);
5027 ctxt->state =
5028 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
5029 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00005030
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005031 } else {
5032 if (elem->refDecl != NULL) {
5033 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
5034 elem->refDecl,
5035 ctxt,
5036 elem->refDecl->
5037 name);
5038 } else {
5039 ctxt->state =
5040 xmlAutomataNewTransition(ctxt->am,
5041 ctxt->state, NULL,
5042 elem->name, type);
5043 }
5044 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
5045 oldstate);
5046 if (elem->minOccurs == 0) {
5047 /* basically an elem* */
5048 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5049 ctxt->state);
5050 }
5051 }
5052 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
5053 xmlAutomataStatePtr tmp;
5054 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00005055
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005056 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
5057 oldstate, NULL);
5058 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00005059
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005060 counter = xmlAutomataNewCounter(ctxt->am,
5061 elem->minOccurs - 1,
5062 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005063
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005064 if (elem->refDecl != NULL) {
5065 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
5066 elem->refDecl, ctxt,
5067 elem->refDecl->name);
5068 } else {
5069 ctxt->state = xmlAutomataNewTransition(ctxt->am,
5070 ctxt->state,
5071 NULL,
5072 elem->name,
5073 type);
5074 }
5075 tmp = ctxt->state;
5076 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
5077 counter);
5078 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
5079 NULL,
5080 counter);
5081 if (elem->minOccurs == 0) {
5082 /* basically an elem? */
5083 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5084 ctxt->state);
5085 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00005086
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005087 } else {
5088 if (elem->refDecl != NULL) {
5089 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
5090 elem->refDecl, ctxt,
5091 elem->refDecl->name);
5092 } else {
5093 ctxt->state = xmlAutomataNewTransition(ctxt->am,
5094 ctxt->state,
5095 NULL,
5096 elem->name,
5097 type);
5098 }
5099 if (elem->minOccurs == 0) {
5100 /* basically an elem? */
5101 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5102 ctxt->state);
5103 }
5104 }
5105 break;
5106 }
5107 case XML_SCHEMA_TYPE_SEQUENCE:{
5108 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005109
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005110 /*
5111 * If max and min occurances are default (1) then
5112 * simply iterate over the subtypes
5113 */
5114 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
5115 subtypes = type->subtypes;
5116 while (subtypes != NULL) {
5117 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
5118 subtypes = subtypes->next;
5119 }
5120 } else {
5121 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005122
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005123 if (type->maxOccurs >= UNBOUNDED) {
5124 if (type->minOccurs > 1) {
5125 xmlAutomataStatePtr tmp;
5126 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005127
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005128 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
5129 oldstate,
5130 NULL);
5131 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005132
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005133 counter = xmlAutomataNewCounter(ctxt->am,
5134 type->
5135 minOccurs - 1,
5136 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00005137
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005138 subtypes = type->subtypes;
5139 while (subtypes != NULL) {
5140 xmlSchemaBuildAContentModel(subtypes, ctxt,
5141 name);
5142 subtypes = subtypes->next;
5143 }
5144 tmp = ctxt->state;
5145 xmlAutomataNewCountedTrans(ctxt->am, tmp,
5146 oldstate, counter);
5147 ctxt->state =
5148 xmlAutomataNewCounterTrans(ctxt->am, tmp,
5149 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00005150
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005151 } else {
5152 subtypes = type->subtypes;
5153 while (subtypes != NULL) {
5154 xmlSchemaBuildAContentModel(subtypes, ctxt,
5155 name);
5156 subtypes = subtypes->next;
5157 }
5158 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
5159 oldstate);
5160 if (type->minOccurs == 0) {
5161 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5162 ctxt->state);
5163 }
5164 }
5165 } else if ((type->maxOccurs > 1)
5166 || (type->minOccurs > 1)) {
5167 xmlAutomataStatePtr tmp;
5168 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005169
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005170 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
5171 oldstate,
5172 NULL);
5173 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00005174
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005175 counter = xmlAutomataNewCounter(ctxt->am,
5176 type->minOccurs -
5177 1,
5178 type->maxOccurs -
5179 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005180
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005181 subtypes = type->subtypes;
5182 while (subtypes != NULL) {
5183 xmlSchemaBuildAContentModel(subtypes, ctxt,
5184 name);
5185 subtypes = subtypes->next;
5186 }
5187 tmp = ctxt->state;
5188 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
5189 counter);
5190 ctxt->state =
5191 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
5192 counter);
5193 if (type->minOccurs == 0) {
5194 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5195 ctxt->state);
5196 }
Daniel Veillardb509f152002-04-17 16:28:10 +00005197
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005198 } else {
5199 subtypes = type->subtypes;
5200 while (subtypes != NULL) {
5201 xmlSchemaBuildAContentModel(subtypes, ctxt,
5202 name);
5203 subtypes = subtypes->next;
5204 }
5205 if (type->minOccurs == 0) {
5206 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5207 ctxt->state);
5208 }
5209 }
5210 }
5211 break;
5212 }
5213 case XML_SCHEMA_TYPE_CHOICE:{
5214 xmlSchemaTypePtr subtypes;
5215 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00005216
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005217 start = ctxt->state;
5218 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00005219
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005220 /*
5221 * iterate over the subtypes and remerge the end with an
5222 * epsilon transition
5223 */
5224 if (type->maxOccurs == 1) {
5225 subtypes = type->subtypes;
5226 while (subtypes != NULL) {
5227 ctxt->state = start;
5228 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
5229 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
5230 subtypes = subtypes->next;
5231 }
5232 } else {
5233 int counter;
5234 xmlAutomataStatePtr hop;
5235 int maxOccurs = type->maxOccurs == UNBOUNDED ?
5236 UNBOUNDED : type->maxOccurs - 1;
5237 int minOccurs =
5238 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00005239
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005240 /*
5241 * use a counter to keep track of the number of transtions
5242 * which went through the choice.
5243 */
5244 counter =
5245 xmlAutomataNewCounter(ctxt->am, minOccurs,
5246 maxOccurs);
5247 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00005248
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005249 subtypes = type->subtypes;
5250 while (subtypes != NULL) {
5251 ctxt->state = start;
5252 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
5253 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
5254 subtypes = subtypes->next;
5255 }
5256 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
5257 counter);
5258 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
5259 counter);
5260 }
5261 if (type->minOccurs == 0) {
5262 xmlAutomataNewEpsilon(ctxt->am, start, end);
5263 }
5264 ctxt->state = end;
5265 break;
5266 }
5267 case XML_SCHEMA_TYPE_ALL:{
5268 xmlAutomataStatePtr start;
5269 xmlSchemaTypePtr subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +00005270 /*
5271 * Changed, since type in not an xmlSchemaElement here.
5272 */
5273 /* xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type; */
5274 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005275 int lax;
5276
5277 subtypes = type->subtypes;
5278 if (subtypes == NULL)
5279 break;
5280 start = ctxt->state;
5281 while (subtypes != NULL) {
5282 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00005283 /*
5284 * the following 'if' was needed to fix bug 139897
5285 * not quite sure why it only needs to be done for
5286 * elements with a 'ref', but it seems to work ok.
5287 */
5288 if (subtypes->ref != NULL)
5289 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
William M. Bracke7091952004-05-11 15:09:58 +00005290 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005291 /* TODO : handle the namespace too */
5292 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
5293 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
5294 ctxt->state, elem->name, 1,
5295 1, subtypes);
5296 } else {
5297 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
5298 ctxt->state, elem->name,
5299 elem->minOccurs,
5300 elem->maxOccurs,
5301 subtypes);
5302 }
5303 subtypes = subtypes->next;
5304 }
5305 lax = type->minOccurs == 0;
5306 ctxt->state =
5307 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
5308 lax);
5309 break;
5310 }
5311 case XML_SCHEMA_TYPE_RESTRICTION:
5312 if (type->subtypes != NULL)
5313 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
5314 break;
5315 case XML_SCHEMA_TYPE_EXTENSION:
5316 if (type->baseType != NULL) {
5317 xmlSchemaTypePtr subtypes;
5318
Daniel Veillardf7627552004-04-22 07:15:40 +00005319 if (type->recurse) {
5320 xmlSchemaPErr(ctxt, type->node,
5321 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
5322 "Schemas: extension type %s is recursive\n",
5323 type->name, NULL);
5324 return;
5325 }
5326 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005327 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00005328 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005329 subtypes = type->subtypes;
5330 while (subtypes != NULL) {
5331 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
5332 subtypes = subtypes->next;
5333 }
5334 } else if (type->subtypes != NULL)
5335 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
5336 break;
5337 case XML_SCHEMA_TYPE_GROUP:
5338 if (type->subtypes == NULL) {
William M. Brack29aa7722004-05-12 00:27:56 +00005339 xmlSchemaTypePtr rgroup;
5340 if (type->ref != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005341 rgroup = xmlSchemaGetGroup(ctxt->schema, type->ref,
William M. Brack29aa7722004-05-12 00:27:56 +00005342 type->refNs);
5343 if (rgroup == NULL) {
5344 xmlSchemaPErr(ctxt, type->node,
5345 XML_SCHEMAP_UNKNOWN_REF,
5346 "Schemas: group %s reference %s is not found",
5347 name, type->ref);
5348 return;
5349 }
5350 xmlSchemaBuildAContentModel(rgroup, ctxt, name);
5351 break;
5352 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005353 }
5354 case XML_SCHEMA_TYPE_COMPLEX:
5355 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5356 if (type->subtypes != NULL)
5357 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
5358 break;
5359 default:
5360 xmlGenericError(xmlGenericErrorContext,
5361 "Found unexpected type %d in %s content model\n",
5362 type->type, name);
5363 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005364 }
5365}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005366
Daniel Veillard4255d502002-04-16 15:50:10 +00005367/**
5368 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005369 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00005370 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005371 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00005372 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005373 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00005374 */
5375static void
5376xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005377 xmlSchemaParserCtxtPtr ctxt,
5378 const xmlChar * name)
5379{
Daniel Veillard4255d502002-04-16 15:50:10 +00005380 xmlAutomataStatePtr start;
5381
Daniel Veillard4255d502002-04-16 15:50:10 +00005382 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005383 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00005384 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005385 elem->contentType = XML_SCHEMA_CONTENT_ANY;
5386 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00005387 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005388 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005389 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005390 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
5391 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005392 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005393
5394#ifdef DEBUG_CONTENT
5395 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005396 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005397#endif
5398
Daniel Veillard4255d502002-04-16 15:50:10 +00005399 ctxt->am = xmlNewAutomata();
5400 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005401 xmlGenericError(xmlGenericErrorContext,
5402 "Cannot create automata for elem %s\n", name);
5403 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005404 }
5405 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
5406 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
5407 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00005408 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005409 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005410 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
5411 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005412 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005413 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
5414 "Content model of %s is not determinist:\n", name,
5415 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00005416 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00005417#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005418 xmlGenericError(xmlGenericErrorContext,
5419 "Content model of %s:\n", name);
5420 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005421#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00005422 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005423 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005424 xmlFreeAutomata(ctxt->am);
5425 ctxt->am = NULL;
5426}
5427
5428/**
5429 * xmlSchemaRefFixupCallback:
5430 * @elem: the schema element context
5431 * @ctxt: the schema parser context
5432 *
5433 * Free the resources associated to the schema parser context
5434 */
5435static void
5436xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005437 xmlSchemaParserCtxtPtr ctxt,
5438 const xmlChar * name,
5439 const xmlChar * context ATTRIBUTE_UNUSED,
5440 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005441{
5442 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005443 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00005444
Daniel Veillard4255d502002-04-16 15:50:10 +00005445 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005446 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005447
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005448 if (elem->subtypes != NULL) {
5449 xmlSchemaPErr(ctxt, elem->node,
5450 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
Daniel Veillard3646d642004-06-02 19:19:14 +00005451 "Schemas: element %s has both ref and subtype\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005452 name, NULL);
5453 return;
5454 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005455 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005456
5457 if (elemDecl == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005458 xmlSchemaPErr(ctxt, elem->node,
5459 XML_SCHEMAP_SRC_RESOLVE,
5460 "Element \"%s\": the QName \"%s\" of the attribute "
5461 "\"ref\" does not resolve to a schema "
5462 "component.\n",
5463 name, elem->ref);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005464 return;
5465 }
5466 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005467 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005468 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005469
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005470 if (elem->subtypes != NULL) {
5471 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
Daniel Veillard3646d642004-06-02 19:19:14 +00005472 "Schemas: element %s has both type and subtype\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005473 name, NULL);
5474 return;
5475 }
5476 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
5477 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00005478
5479 if (typeDecl == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005480 xmlSchemaPErr(ctxt, elem->node,
5481 XML_SCHEMAP_SRC_RESOLVE,
5482 "Element \"%s\": the QName \"%s\" of the attribute "
5483 "\"type\" does not resolve to a schema "
5484 "component.\n", name, elem->namedType);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005485 return;
5486 }
5487 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005488 }
5489}
5490
William M. Bracke7091952004-05-11 15:09:58 +00005491/**
5492 * xmlSchemaParseListRefFixup:
5493 * @type: the schema type definition
5494 * @ctxt: the schema parser context
5495 *
5496 * Fixup of the itemType reference of the list type.
5497 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00005498static void
William M. Bracke7091952004-05-11 15:09:58 +00005499xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005500{
5501 /*
5502 * src-list-itemType-or-simpleType
5503 * Either the itemType [attribute] or the <simpleType> [child] of
5504 * the <list> element must be present, but not both.
5505 */
5506 if (((type->base == NULL) &&
5507 (type->subtypes == NULL)) ||
5508 ((type->base != NULL) &&
5509 (type->subtypes != NULL))) {
5510 /*
5511 * src-restriction-base-or-simpleType
5512 * Either the base [attribute] or the simpleType [child] of the
5513 * <restriction> element must be present, but not both.
5514 */
5515 xmlSchemaPErr(ctxt, type->node,
5516 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
5517 "List \"%s\": "
5518 "Either the \"base\" attribute or the <simpleType> child "
5519 "must be present, but not both.\n",
5520 type->name, NULL);
5521 } else if (type->base!= NULL) {
5522 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
5523 if (type->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005524 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_TYPE,
Daniel Veillard01fa6152004-06-29 17:04:39 +00005525 "List \"%s\" references an unknown item type: \"%s\"\n",
5526 type->name, type->base);
5527 }
5528 }
5529 if ((type->subtypes != NULL) &&
5530 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
5531 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005532}
5533
5534/**
5535 * xmlSchemaParseUnionRefCheck:
5536 * @typeDecl: the schema type definition
5537 * @ctxt: the schema parser context
5538 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005539 * Checks and builds the memberTypes of the union type.
5540 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00005541 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005542static int
William M. Bracke7091952004-05-11 15:09:58 +00005543xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00005544 xmlSchemaParserCtxtPtr ctxt)
5545{
5546 const xmlChar *cur, *end, *prefix, *ncName, *namespace;
5547 xmlChar *tmp;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005548 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
5549 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005550 xmlNsPtr ns;
5551 int len;
5552
Daniel Veillard01fa6152004-06-29 17:04:39 +00005553 /* 1 If the <union> alternative is chosen, then [Definition:]
5554 * define the explicit members as the type definitions ·resolved·
5555 * to by the items in the ·actual value· of the memberTypes [attribute],
5556 * if any, followed by the type definitions corresponding to the
5557 * <simpleType>s among the [children] of <union>, if any.
5558 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00005559
Daniel Veillard01fa6152004-06-29 17:04:39 +00005560 if (type->type != XML_SCHEMA_TYPE_UNION)
5561 return (-1);
5562 if (ctxt->ctxtType == NULL) {
5563 xmlSchemaPErr(ctxt, type->node,
5564 XML_SCHEMAS_ERR_INTERNAL,
5565 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
5566 "available", NULL, NULL);
5567 return (-1);
5568 }
5569 /*
5570 * src-union-memberTypes-or-simpleTypes
5571 * Either the memberTypes [attribute] of the <union> element must
5572 * be non-empty or there must be at least one simpleType [child].
5573 */
5574 if ((type->base == NULL) &&
5575 (type->subtypes == NULL)) {
5576 /*
5577 * src-restriction-base-or-simpleType
5578 * Either the base [attribute] or the simpleType [child] of the
5579 * <restriction> element must be present, but not both.
5580 */
5581 xmlSchemaPErr(ctxt, type->node,
5582 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
5583 "Union \"%s\": "
5584 "Either the \"memberTypes\" attribute must be non-empty "
5585 "or there must be at least one <simpleType> child.\n",
5586 type->name, NULL);
5587 }
5588
5589 ctxtType = ctxt->ctxtType;
5590 if (type->base != NULL) {
5591 cur = type->base;
5592 do {
5593 while (IS_BLANK_CH(*cur))
5594 cur++;
5595 end = cur;
5596 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5597 end++;
5598 if (end == cur)
5599 break;
5600 tmp = xmlStrndup(cur, end - cur);
5601 ncName = xmlSplitQName3(tmp, &len);
5602 if (ncName != NULL) {
5603 prefix = xmlDictLookup(ctxt->dict, tmp, len);
5604 } else {
5605 prefix = NULL;
5606 ncName = tmp;
5607 }
5608 ns = xmlSearchNs(type->node->doc, type->node, prefix);
5609 if (ns == NULL) {
5610 if (prefix != NULL) {
5611 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_PREFIX_UNDEFINED,
5612 "Union \"%s\": the namespace prefix of member type "
5613 "\"%s\" is undefined\n",
5614 type->name, (const xmlChar *) tmp);
5615 }
5616 namespace = NULL;
5617 } else {
5618 namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
5619 }
5620 memberType = xmlSchemaGetType(ctxt->schema, ncName, namespace);
5621 if (memberType == NULL) {
5622 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
5623 "Union \"%s\" references an unknown member type \"%s\".\n",
5624 type->name, (const xmlChar *) tmp);
5625 } else {
5626 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
5627 xmlSchemaTypeFixup(memberType, ctxt, NULL);
5628 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
5629 if (link == NULL) {
5630 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
5631 return (-1);
5632 }
5633 link->type = memberType;
5634 link->next = NULL;
5635 if (lastLink == NULL)
5636 ctxtType->memberTypes = link;
5637 else
5638 lastLink->next = link;
5639 lastLink = link;
5640 }
5641 xmlFree(tmp);
5642 cur = end;
5643 } while (*cur != 0);
5644 }
5645 /*
5646 * Add local simple types,
5647 */
5648 memberType = type->subtypes;
5649 while (memberType != NULL) {
5650 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
5651 xmlSchemaTypeFixup(memberType, ctxt, NULL);
5652 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
5653 if (link == NULL) {
5654 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
5655 return (-1);
5656 }
5657 link->type = memberType;
5658 link->next = NULL;
5659 if (lastLink == NULL)
5660 ctxtType->memberTypes = link;
5661 else
5662 lastLink->next = link;
5663 lastLink = link;
5664 memberType = memberType->next;
5665 }
5666 /*
5667 * The actual value is then formed by replacing any union type
5668 * definition in the ·explicit members· with the members of their
5669 * {member type definitions}, in order.
5670 */
5671 link = ctxtType->memberTypes;
5672 while (link != NULL) {
5673 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
5674 subLink = link->type->memberTypes;
5675 if (subLink != NULL) {
5676 link->type = subLink->type;
5677 if (subLink->next != NULL) {
5678 lastLink = link->next;
5679 subLink = subLink->next;
5680 prevLink = link;
5681 while (subLink != NULL) {
5682 newLink = (xmlSchemaTypeLinkPtr)
5683 xmlMalloc(sizeof(xmlSchemaTypeLink));
5684 if (newLink == NULL) {
5685 xmlSchemaPErrMemory(ctxt, "allocating a type link",
5686 NULL);
5687 return (-1);
5688 }
5689 newLink->type = memberType;
5690 prevLink->next = newLink;
5691 prevLink = newLink;
5692 newLink->next = lastLink;
5693
5694 subLink = subLink->next;
5695 }
5696 }
5697 }
5698 }
5699 link = link->next;
5700 }
5701
5702 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005703}
5704
Daniel Veillard4255d502002-04-16 15:50:10 +00005705/**
Daniel Veillard3646d642004-06-02 19:19:14 +00005706 * xmlSchemaGetOnymousTypeName:
5707 * @attr: the attribute declaration/use
5708 *
5709 * Returns the name of the attribute; if the attribute
5710 * is a reference, the name of the referenced global type will be returned.
5711 */
5712static const xmlChar *
5713xmlSchemaGetOnymousAttrName(xmlSchemaAttributePtr attr)
5714{
5715 if (attr->ref != NULL)
5716 return(attr->ref);
5717 else
5718 return(attr->name);
5719}
5720
5721/**
5722 * xmlSchemaGetOnymousTargetNsURI:
5723 * @type: the type (element or attribute)
5724 *
5725 * Returns the target namespace URI of the type; if the type is a reference,
5726 * the target namespace of the referenced type will be returned.
5727 */
5728static const xmlChar *
5729xmlSchemaGetOnymousTargetNsURI(xmlSchemaTypePtr type)
5730{
5731 if (type->type == XML_SCHEMA_TYPE_ELEMENT) {
5732 if (type->ref != NULL)
5733 return(((xmlSchemaElementPtr)((xmlSchemaElementPtr)
5734 type)->subtypes)->targetNamespace);
5735 else
5736 return(((xmlSchemaElementPtr) type)->targetNamespace);
5737 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
5738 if (type->ref != NULL)
5739 return(((xmlSchemaAttributePtr)((xmlSchemaAttributePtr)
5740 type)->subtypes)->targetNamespace);
5741 else
5742 return(((xmlSchemaAttributePtr) type)->targetNamespace);
5743 } else
5744 return (NULL);
5745}
5746
5747/**
5748 * xmlSchemaIsDerivedFromBuiltInType:
5749 * @ctxt: the schema parser context
5750 * @type: the type definition
5751 * @valType: the value type
5752 *
5753 *
5754 * Returns 1 if the type has the given value type, or
5755 * is derived from such a type.
5756 */
William M. Brack803812b2004-06-03 02:11:24 +00005757static int
Daniel Veillard3646d642004-06-02 19:19:14 +00005758xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
5759 xmlSchemaTypePtr type, int valType)
5760{
5761 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005762 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00005763 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005764 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00005765 return(1);
5766 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
5767 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
5768 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
5769 ((xmlSchemaAttributePtr) type)->subtypes, valType));
5770 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
5771 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
5772 if (type->baseType != NULL)
5773 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
5774 valType));
5775 } else if ((type->subtypes != NULL) &&
5776 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
5777 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
5778 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
5779 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
5780 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
5781 valType));
5782 }
5783
5784 return (0);
5785}
5786
5787/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00005788 * xmlSchemaIsDerivedFromBuiltInType:
5789 * @type: the simpleType definition
5790 *
5791 * Returns the primitive type of the given type or
5792 * NULL in case of error.
5793 */
5794static xmlSchemaTypePtr
5795xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
5796{
5797 while (type != NULL) {
5798 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
5799 return (type);
5800 type = type->baseType;
5801 }
5802
5803 return (NULL);
5804}
5805
5806
5807/**
Daniel Veillard3646d642004-06-02 19:19:14 +00005808 * xmlSchemaBuildAttributeUsesOwned:
5809 * @ctxt: the schema parser context
5810 * @type: the complex type definition
5811 * @cur: the attribute declaration list
5812 * @lastUse: the top of the attribute use list
5813 *
5814 * Builds the attribute uses list on the given complex type.
5815 * This one is supposed to be called by
5816 * xmlSchemaBuildAttributeValidation only.
5817 */
5818static int
5819xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
5820 xmlSchemaAttributePtr cur,
5821 xmlSchemaAttributeLinkPtr *uses,
5822 xmlSchemaAttributeLinkPtr *lastUse)
5823{
5824 xmlSchemaAttributeLinkPtr tmp;
5825 while (cur != NULL) {
5826 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
5827 /*
5828 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
5829 * to by the ·actual value·s of the ref [attribute] of the
5830 * <attributeGroup> [children], if any."
5831 */
5832 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
5833 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
5834 lastUse) == -1) {
5835 return (-1);
5836 }
5837 } else {
5838 /* W3C: "1 The set of attribute uses corresponding to the
5839 * <attribute> [children], if any."
5840 */
5841 tmp = (xmlSchemaAttributeLinkPtr)
5842 xmlMalloc(sizeof(xmlSchemaAttributeLink));
5843 if (tmp == NULL) {
5844 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
5845 return (-1);
5846 }
5847 tmp->attr = cur;
5848 tmp->next = NULL;
5849 if (*uses == NULL)
5850 *uses = tmp;
5851 else
5852 (*lastUse)->next = tmp;
5853 *lastUse = tmp;
5854 }
5855 cur = cur->next;
5856 }
5857 return (0);
5858}
5859
Daniel Veillard50355f02004-06-08 17:52:16 +00005860/**
5861 * xmlSchemaCloneWildcardNsConstraints:
5862 * @ctxt: the schema parser context
5863 * @dest: the destination wildcard
5864 * @source: the source wildcard
5865 *
5866 * Clones the namespace constraints of source
5867 * and assignes them to dest.
5868 * Returns -1 on internal error, 0 otherwise.
5869 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005870static int
5871xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
5872 xmlSchemaWildcardPtr *dest,
5873 xmlSchemaWildcardPtr source)
5874{
5875 xmlSchemaWildcardNsPtr cur, tmp, last;
5876
5877 if ((source == NULL) || (*dest == NULL))
5878 return(-1);
5879 (*dest)->any = source->any;
5880 cur = source->nsSet;
5881 last = NULL;
5882 while (cur != NULL) {
5883 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5884 if (tmp == NULL)
5885 return(-1);
5886 tmp->value = cur->value;
5887 if (last == NULL)
5888 (*dest)->nsSet = tmp;
5889 else
5890 last->next = tmp;
5891 last = tmp;
5892 cur = cur->next;
5893 }
5894 if ((*dest)->negNsSet != NULL)
5895 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
5896 if (source->negNsSet != NULL) {
5897 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5898 if ((*dest)->negNsSet == NULL)
5899 return(-1);
5900 (*dest)->negNsSet->value = source->negNsSet->value;
5901 } else
5902 (*dest)->negNsSet = NULL;
5903 return(0);
5904}
5905
Daniel Veillard50355f02004-06-08 17:52:16 +00005906/**
5907 * xmlSchemaUnionWildcards:
5908 * @ctxt: the schema parser context
5909 * @completeWild: the first wildcard
5910 * @curWild: the second wildcard
5911 *
5912 * Unions the namespace constraints of the given wildcards.
5913 * @completeWild will hold the resulting union.
5914 * Returns a positive error code on failure, -1 in case of an
5915 * internal error, 0 otherwise.
5916 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005917static int
5918xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
5919 xmlSchemaWildcardPtr completeWild,
5920 xmlSchemaWildcardPtr curWild)
5921{
5922 xmlSchemaWildcardNsPtr cur, curB, tmp;
5923
5924 /*
5925 * 1 If O1 and O2 are the same value, then that value must be the
5926 * value.
5927 */
5928 if ((completeWild->any == curWild->any) &&
5929 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
5930 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
5931
5932 if ((completeWild->negNsSet == NULL) ||
5933 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
5934
5935 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00005936 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00005937
5938 /*
5939 * Check equality of sets.
5940 */
5941 cur = completeWild->nsSet;
5942 while (cur != NULL) {
5943 found = 0;
5944 curB = curWild->nsSet;
5945 while (curB != NULL) {
5946 if (cur->value == curB->value) {
5947 found = 1;
5948 break;
5949 }
5950 curB = curB->next;
5951 }
5952 if (!found)
5953 break;
5954 cur = cur->next;
5955 }
5956 if (found)
5957 return(0);
5958 } else
5959 return(0);
5960 }
5961 }
5962 /*
5963 * 2 If either O1 or O2 is any, then any must be the value
5964 */
Daniel Veillard50355f02004-06-08 17:52:16 +00005965 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005966 if (completeWild->any == 0) {
5967 completeWild->any = 1;
5968 if (completeWild->nsSet != NULL) {
5969 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
5970 completeWild->nsSet = NULL;
5971 }
5972 if (completeWild->negNsSet != NULL) {
5973 xmlFree(completeWild->negNsSet);
5974 completeWild->negNsSet = NULL;
5975 }
5976 }
Daniel Veillard50355f02004-06-08 17:52:16 +00005977 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00005978 }
5979 /*
5980 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
5981 * then the union of those sets must be the value.
5982 */
5983 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
5984 int found;
5985 xmlSchemaWildcardNsPtr start;
5986
5987 cur = curWild->nsSet;
5988 start = completeWild->nsSet;
5989 while (cur != NULL) {
5990 found = 0;
5991 curB = start;
5992 while (curB != NULL) {
5993 if (cur->value == curB->value) {
5994 found = 1;
5995 break;
5996 }
5997 curB = curB->next;
5998 }
5999 if (!found) {
6000 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6001 if (tmp == NULL)
6002 return (-1);
6003 tmp->value = cur->value;
6004 tmp->next = completeWild->nsSet;
6005 completeWild->nsSet = tmp;
6006 }
6007 cur = cur->next;
6008 }
6009
6010 return(0);
6011 }
6012 /*
6013 * 4 If the two are negations of different values (namespace names
6014 * or ·absent·), then a pair of not and ·absent· must be the value.
6015 */
6016 if ((completeWild->negNsSet != NULL) &&
6017 (curWild->negNsSet != NULL) &&
6018 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
6019 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00006020
6021 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00006022 }
6023 /*
6024 * 5.
6025 */
6026 if (((completeWild->negNsSet != NULL) &&
6027 (completeWild->negNsSet->value != NULL) &&
6028 (curWild->nsSet != NULL)) ||
6029 ((curWild->negNsSet != NULL) &&
6030 (curWild->negNsSet->value != NULL) &&
6031 (completeWild->nsSet != NULL))) {
6032
6033 int nsFound, absentFound = 0;
6034
6035 if (completeWild->nsSet != NULL) {
6036 cur = completeWild->nsSet;
6037 curB = curWild->negNsSet;
6038 } else {
6039 cur = curWild->nsSet;
6040 curB = completeWild->negNsSet;
6041 }
6042 nsFound = 0;
6043 while (cur != NULL) {
6044 if (cur->value == NULL)
6045 absentFound = 1;
6046 else if (cur->value == curB->value)
6047 nsFound = 1;
6048 if (nsFound && absentFound)
6049 break;
6050 cur = cur->next;
6051 }
6052
6053 if (nsFound && absentFound) {
6054 /*
6055 * 5.1 If the set S includes both the negated namespace
6056 * name and ·absent·, then any must be the value.
6057 */
6058 completeWild->any = 1;
6059 if (completeWild->nsSet != NULL) {
6060 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6061 completeWild->nsSet = NULL;
6062 }
6063 if (completeWild->negNsSet != NULL) {
6064 xmlFree(completeWild->negNsSet);
6065 completeWild->negNsSet = NULL;
6066 }
6067 } else if (nsFound && (!absentFound)) {
6068 /*
6069 * 5.2 If the set S includes the negated namespace name
6070 * but not ·absent·, then a pair of not and ·absent· must
6071 * be the value.
6072 */
6073 if (completeWild->nsSet != NULL) {
6074 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6075 completeWild->nsSet = NULL;
6076 }
6077 if (completeWild->negNsSet == NULL) {
6078 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6079 if (completeWild->negNsSet == NULL)
6080 return (-1);
6081 }
6082 completeWild->negNsSet->value = NULL;
6083 } else if ((!nsFound) && absentFound) {
6084 /*
6085 * 5.3 If the set S includes ·absent· but not the negated
6086 * namespace name, then the union is not expressible.
6087 */
6088 xmlSchemaPErr(ctxt, completeWild->node,
6089 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
6090 "The union of the wilcard is not expressible\n",
6091 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00006092 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00006093 } else if ((!nsFound) && (!absentFound)) {
6094 /*
6095 * 5.4 If the set S does not include either the negated namespace
6096 * name or ·absent·, then whichever of O1 or O2 is a pair of not
6097 * and a namespace name must be the value.
6098 */
6099 if (completeWild->negNsSet == NULL) {
6100 if (completeWild->nsSet != NULL) {
6101 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6102 completeWild->nsSet = NULL;
6103 }
6104 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6105 if (completeWild->negNsSet == NULL)
6106 return (-1);
6107 completeWild->negNsSet->value = curWild->negNsSet->value;
6108 }
6109 }
6110 return (0);
6111 }
6112 /*
6113 * 6.
6114 */
6115 if (((completeWild->negNsSet != NULL) &&
6116 (completeWild->negNsSet->value == NULL) &&
6117 (curWild->nsSet != NULL)) ||
6118 ((curWild->negNsSet != NULL) &&
6119 (curWild->negNsSet->value == NULL) &&
6120 (completeWild->nsSet != NULL))) {
6121
6122 if (completeWild->nsSet != NULL) {
6123 cur = completeWild->nsSet;
6124 } else {
6125 cur = curWild->nsSet;
6126 }
6127 while (cur != NULL) {
6128 if (cur->value == NULL) {
6129 /*
6130 * 6.1 If the set S includes ·absent·, then any must be the
6131 * value.
6132 */
6133 completeWild->any = 1;
6134 if (completeWild->nsSet != NULL) {
6135 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6136 completeWild->nsSet = NULL;
6137 }
6138 if (completeWild->negNsSet != NULL) {
6139 xmlFree(completeWild->negNsSet);
6140 completeWild->negNsSet = NULL;
6141 }
6142 return (0);
6143 }
6144 cur = cur->next;
6145 }
6146 if (completeWild->negNsSet == NULL) {
6147 /*
6148 * 6.2 If the set S does not include ·absent·, then a pair of not
6149 * and ·absent· must be the value.
6150 */
6151 if (completeWild->nsSet != NULL) {
6152 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6153 completeWild->nsSet = NULL;
6154 }
6155 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6156 if (completeWild->negNsSet == NULL)
6157 return (-1);
6158 completeWild->negNsSet->value = NULL;
6159 }
6160 return (0);
6161 }
6162 return (0);
6163
6164}
6165
Daniel Veillard50355f02004-06-08 17:52:16 +00006166/**
6167 * xmlSchemaIntersectWildcards:
6168 * @ctxt: the schema parser context
6169 * @completeWild: the first wildcard
6170 * @curWild: the second wildcard
6171 *
6172 * Intersects the namespace constraints of the given wildcards.
6173 * @completeWild will hold the resulting intersection.
6174 * Returns a positive error code on failure, -1 in case of an
6175 * internal error, 0 otherwise.
6176 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006177static int
6178xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
6179 xmlSchemaWildcardPtr completeWild,
6180 xmlSchemaWildcardPtr curWild)
6181{
William M. Brack803812b2004-06-03 02:11:24 +00006182 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00006183
6184 /*
6185 * 1 If O1 and O2 are the same value, then that value must be the
6186 * value.
6187 */
6188 if ((completeWild->any == curWild->any) &&
6189 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
6190 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
6191
6192 if ((completeWild->negNsSet == NULL) ||
6193 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
6194
6195 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00006196 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00006197
6198 /*
6199 * Check equality of sets.
6200 */
6201 cur = completeWild->nsSet;
6202 while (cur != NULL) {
6203 found = 0;
6204 curB = curWild->nsSet;
6205 while (curB != NULL) {
6206 if (cur->value == curB->value) {
6207 found = 1;
6208 break;
6209 }
6210 curB = curB->next;
6211 }
6212 if (!found)
6213 break;
6214 cur = cur->next;
6215 }
6216 if (found)
6217 return(0);
6218 } else
6219 return(0);
6220 }
6221 }
6222 /*
6223 * 2 If either O1 or O2 is any, then the other must be the value.
6224 */
6225 if ((completeWild->any != curWild->any) && (completeWild->any)) {
6226 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
6227 return(-1);
6228 return(0);
6229 }
6230 /*
6231 * 3 If either O1 or O2 is a pair of not and a value (a namespace
6232 * name or ·absent·) and the other is a set of (namespace names or
6233 * ·absent·), then that set, minus the negated value if it was in
6234 * the set, minus ·absent· if it was in the set, must be the value.
6235 */
6236 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
6237 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
6238 const xmlChar *neg;
6239
6240 if (completeWild->nsSet == NULL) {
6241 neg = completeWild->negNsSet->value;
6242 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
6243 return(-1);
6244 } else
6245 neg = curWild->negNsSet->value;
6246 /*
6247 * Remove absent and negated.
6248 */
6249 prev = NULL;
6250 cur = completeWild->nsSet;
6251 while (cur != NULL) {
6252 if (cur->value == NULL) {
6253 if (prev == NULL)
6254 completeWild->nsSet = cur->next;
6255 else
6256 prev->next = cur->next;
6257 xmlFree(cur);
6258 break;
6259 }
6260 prev = cur;
6261 cur = cur->next;
6262 }
6263 if (neg != NULL) {
6264 prev = NULL;
6265 cur = completeWild->nsSet;
6266 while (cur != NULL) {
6267 if (cur->value == neg) {
6268 if (prev == NULL)
6269 completeWild->nsSet = cur->next;
6270 else
6271 prev->next = cur->next;
6272 xmlFree(cur);
6273 break;
6274 }
6275 prev = cur;
6276 cur = cur->next;
6277 }
6278 }
6279
6280 return(0);
6281 }
6282 /*
6283 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
6284 * then the intersection of those sets must be the value.
6285 */
6286 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
6287 int found;
6288
6289 cur = completeWild->nsSet;
6290 prev = NULL;
6291 while (cur != NULL) {
6292 found = 0;
6293 curB = curWild->nsSet;
6294 while (curB != NULL) {
6295 if (cur->value == curB->value) {
6296 found = 1;
6297 break;
6298 }
6299 curB = curB->next;
6300 }
6301 if (!found) {
6302 if (prev == NULL)
6303 completeWild->nsSet = cur->next;
6304 else
6305 prev->next = cur->next;
6306 tmp = cur->next;
6307 xmlFree(cur);
6308 cur = tmp;
6309 continue;
6310 }
6311 prev = cur;
6312 cur = cur->next;
6313 }
6314
6315 return(0);
6316 }
6317 /* 5 If the two are negations of different namespace names,
6318 * then the intersection is not expressible
6319 */
6320 if ((completeWild->negNsSet != NULL) &&
6321 (curWild->negNsSet != NULL) &&
6322 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
6323 (completeWild->negNsSet->value != NULL) &&
6324 (curWild->negNsSet->value != NULL)) {
6325
6326 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
6327 "The intersection of the wilcard is not expressible\n",
6328 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00006329 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00006330 }
6331 /*
6332 * 6 If the one is a negation of a namespace name and the other
6333 * is a negation of ·absent·, then the one which is the negation
6334 * of a namespace name must be the value.
6335 */
6336 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
6337 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
6338 (completeWild->negNsSet->value == NULL)) {
6339 completeWild->negNsSet->value = curWild->negNsSet->value;
6340 }
6341 return(0);
6342}
6343
Daniel Veillard50355f02004-06-08 17:52:16 +00006344/**
6345 * xmlSchemaIsWildcardNsConstraintSubset:
6346 * @ctxt: the schema parser context
6347 * @wildA: the first wildcard
6348 * @wildB: the second wildcard
6349 *
6350 * Returns 1 if the namespace constraint of @wildA is an intensional
6351 * subset of @wildB, 0 otherwise.
6352 */
6353static int
6354xmlSchemaIsWildcardNsConstraintSubset(
6355 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
6356 xmlSchemaWildcardPtr wildA,
6357 xmlSchemaWildcardPtr wildB)
6358{
Daniel Veillard3646d642004-06-02 19:19:14 +00006359
Daniel Veillard50355f02004-06-08 17:52:16 +00006360 /*
6361 * Schema Component Constraint: Wildcard Subset
6362 */
6363 /*
6364 * 1 super must be any.
6365 */
6366 if (wildB->any)
6367 return (1);
6368 /*
6369 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
6370 * 2.2 super must be a pair of not and the same value.
6371 */
6372 if ((wildA->negNsSet != NULL) &&
6373 (wildB->negNsSet != NULL) &&
6374 (wildA->negNsSet->value == wildA->negNsSet->value))
6375 return (1);
6376 /*
6377 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
6378 */
6379 if (wildA->nsSet != NULL) {
6380 /*
6381 * 3.2.1 super must be the same set or a superset thereof.
6382 */
6383 if (wildB->nsSet != NULL) {
6384 xmlSchemaWildcardNsPtr cur, curB;
6385 int found = 0;
6386
6387 cur = wildA->nsSet;
6388 while (cur != NULL) {
6389 found = 0;
6390 curB = wildB->nsSet;
6391 while (curB != NULL) {
6392 if (cur->value == curB->value) {
6393 found = 1;
6394 break;
6395 }
6396 curB = curB->next;
6397 }
6398 if (!found)
6399 return (0);
6400 cur = cur->next;
6401 }
6402 if (found)
6403 return (1);
6404 } else if (wildB->negNsSet != NULL) {
6405 xmlSchemaWildcardNsPtr cur;
6406 /*
6407 * 3.2.2 super must be a pair of not and a namespace name or
6408 * ·absent· and that value must not be in sub's set.
6409 */
6410 cur = wildA->nsSet;
6411 while (cur != NULL) {
6412 if (cur->value == wildB->negNsSet->value)
6413 return (0);
6414 cur = cur->next;
6415 }
6416 return (1);
6417 }
6418 }
6419 return (0);
6420}
6421
6422/**
6423 * xmlSchemaBuildCompleteAttributeWildcard:
6424 * @ctxt: the schema parser context
6425 * @attrs: the attribute list
6426 * @completeWild: the resulting complete wildcard
6427 *
6428 * Returns -1 in case of an internal error, 0 otherwise.
6429 */
6430static int
6431xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
6432 xmlSchemaAttributePtr attrs,
6433 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00006434{
6435 while (attrs != NULL) {
6436 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6437 xmlSchemaAttributeGroupPtr group;
6438
6439 group = (xmlSchemaAttributeGroupPtr) attrs;
6440 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
6441 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00006442 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
6443 group->attributes, &group->attributeWildcard) == -1)
6444 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00006445 }
6446 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
6447 }
6448 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00006449 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006450 /*
6451 * Copy the first encountered wildcard as context, except for the annotation.
6452 */
Daniel Veillard50355f02004-06-08 17:52:16 +00006453 *completeWild = xmlSchemaAddWildcard(ctxt);
6454 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
6455 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
6456 completeWild, group->attributeWildcard) == -1)
6457 return (-1);
6458 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00006459 /*
6460 * Although the complete wildcard might not correspond to any
6461 * node in the schema, we will save this context node.
6462 */
Daniel Veillard50355f02004-06-08 17:52:16 +00006463 (*completeWild)->node = group->attributeWildcard->node;
6464
6465 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
6466 xmlSchemaFreeWildcard(*completeWild);
6467 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00006468 }
6469 }
6470 }
6471 attrs = attrs->next;
6472 }
6473
Daniel Veillard50355f02004-06-08 17:52:16 +00006474 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00006475}
6476
6477/**
6478 * xmlSchemaMatchesWildcardNs:
6479 * @wild: the wildcard
6480 * @ns: the namespace
6481 *
6482 *
6483 * Returns 1 if the given namespace matches the wildcard,
6484 * 0 otherwise.
6485 */
6486static int
6487xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
6488{
6489 if (wild == NULL)
6490 return(0);
6491
6492 if (wild->any)
6493 return(1);
6494 else if (wild->nsSet != NULL) {
6495 xmlSchemaWildcardNsPtr cur;
6496
6497 cur = wild->nsSet;
6498 while (cur != NULL) {
6499 if (xmlStrEqual(cur->value, ns))
6500 return(1);
6501 cur = cur->next;
6502 }
6503 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
6504 (!xmlStrEqual(wild->negNsSet->value, ns)))
6505 return(1);
6506
6507 return(0);
6508}
6509
6510/**
6511 * xmlSchemaBuildAttributeValidation:
6512 * @ctxt: the schema parser context
6513 * @type: the complex type definition
6514 *
6515 *
6516 * Builds the wildcard and the attribute uses on the given complex type.
6517 * Returns -1 if an internal error occurs, 0 otherwise.
6518 */
6519static int
6520xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
6521{
6522 xmlSchemaTypePtr baseType = NULL;
6523 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +00006524 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00006525 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006526 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +00006527 int baseIsAnyType = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00006528
Daniel Veillard01fa6152004-06-29 17:04:39 +00006529 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +00006530 /*
6531 * Complex Type Definition with complex content Schema Component.
6532 *
6533 * Attribute uses.
6534 */
6535 if (type->attributeUses != NULL) {
6536 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00006537 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +00006538 "attribute uses already builded.\n",
6539 NULL, NULL);
6540 return (-1);
6541 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006542 if (type->baseType == NULL) {
6543 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
6544 "Internal error: xmlSchemaBuildAttributeValidation: "
6545 "complex type \"%s\" has no base type.\n",
6546 type->name, NULL);
6547 return (-1);
6548 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006549
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006550 baseType = type->baseType;
6551 if (baseType == NULL) {
6552 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
6553 "Internal error: xmlSchemaBuildAttributeValidation: "
6554 "type has no base type.\n",
6555 NULL, NULL);
6556 return (-1);
6557 }
6558
6559 if (baseType == anyType)
6560 baseIsAnyType = 1;
6561 /*
6562 * Inherit the attribute uses of the base type.
6563 */
6564 /*
6565 * NOTE: It is allowed to "extend" the anyType complex type.
6566 */
6567 if (!baseIsAnyType) {
6568 if (baseType != NULL) {
6569 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
6570 tmp = (xmlSchemaAttributeLinkPtr)
6571 xmlMalloc(sizeof(xmlSchemaAttributeLink));
6572 if (tmp == NULL) {
6573 xmlSchemaPErrMemory(ctxt,
6574 "building attribute uses of complexType", NULL);
6575 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00006576 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006577 tmp->attr = cur->attr;
6578 tmp->next = NULL;
6579 if (type->attributeUses == NULL) {
6580 type->attributeUses = tmp;
6581 } else
6582 lastBaseUse->next = tmp;
6583 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00006584 }
6585 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006586 }
6587 if ((type->subtypes != NULL) &&
6588 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
6589 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
6590 attrs = type->subtypes->subtypes->attributes;
6591 type->attributeWildcard = type->subtypes->subtypes->attributeWildcard;
6592 } else {
6593 /* Short hand form of the complexType. */
6594 attrs = type->attributes;
6595 }
6596 /*
6597 * Handle attribute wildcards.
6598 */
6599 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
6600 attrs, &type->attributeWildcard) == -1) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006601 if ((type->attributeWildcard != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00006602 /* Either we used the short hand form... */
6603 ((type->subtypes == NULL) ||
6604 /* Or complexType -> restriction/extension */
6605 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
Daniel Veillard3646d642004-06-02 19:19:14 +00006606 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006607 return (-1);
6608 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006609 /*
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006610 * TODO: This "onwed_attr_wildcard" is quite sensless: we should
6611 * create the wildcard right from the start on the complexType,
6612 * rather than on the <restriction>/<extension>.
Daniel Veillard01fa6152004-06-29 17:04:39 +00006613 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006614 if ((type->attributeWildcard != NULL) &&
6615 /* Either we used the short hand form... */
6616 ((type->subtypes == NULL) ||
6617 /* Or complexType -> restriction/extension */
6618 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
6619 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6620
6621 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
6622 ((baseIsAnyType) ||
6623 ((baseType != NULL) &&
6624 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
6625 (baseType->attributeWildcard != NULL)))) {
6626 if (type->attributeWildcard != NULL) {
6627 /*
6628 * Union the complete wildcard with the base wildcard.
6629 */
6630 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
6631 baseType->attributeWildcard) == -1)
6632 return (-1);
6633 } else {
6634 /*
6635 * Just inherit the wildcard.
6636 */
6637 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +00006638 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006639 }
6640
6641 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
6642 if (type->attributeWildcard != NULL) {
6643 /*
6644 * Derivation Valid (Restriction, Complex)
6645 * 4.1 The {base type definition} must also have one.
6646 */
6647 if (baseType->attributeWildcard == NULL) {
6648 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
6649 "The derived type \"%s\" has an attribute wildcard, "
6650 "but the base type \"%s\" does not have one.\n",
6651 type->name, baseType->name);
6652 return (1);
6653 } else if (xmlSchemaIsWildcardNsConstraintSubset(ctxt,
6654 type->attributeWildcard, baseType->attributeWildcard) == 0) {
6655 /* 4.2 */
6656 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
6657 "The wildcard in the derived type \"%s\" is not a valid "
6658 "subset of the one in the base type \"%s\".\n",
6659 type->name, baseType->name);
6660 return (1);
6661 }
6662 /* 4.3 Unless the {base type definition} is the ·ur-type
6663 * definition·, the complex type definition's {attribute
6664 * wildcard}'s {process contents} must be identical to or
6665 * stronger than the {base type definition}'s {attribute
6666 * wildcard}'s {process contents}, where strict is stronger
6667 * than lax is stronger than skip.
6668 */
6669 if ((type->baseType != anyType) &&
6670 (type->attributeWildcard->processContents <
6671 baseType->attributeWildcard->processContents)) {
6672 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
6673 "The process contents of the wildcard in the "
6674 "derived type \"%s\" is weaker than "
6675 "that in the base type \"%s\".\n",
6676 type->name, baseType->name);
6677 return (1);
6678 }
6679 }
6680 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
6681 /*
6682 * Derivation Valid (Extension)
6683 * At this point the type and the base have both, either
6684 * no wildcard or a wildcard.
6685 */
6686 if ((baseType->attributeWildcard != NULL) &&
6687 (baseType->attributeWildcard != type->attributeWildcard)) {
6688 /* 1.3 */
6689 if (xmlSchemaIsWildcardNsConstraintSubset(ctxt,
6690 baseType->attributeWildcard, type->attributeWildcard) == 0) {
6691 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_COS_CT_EXTENDS_1_3,
6692 "The wildcard in the derived type \"%s\" is not a valid "
6693 "superset of the one in the base type \"%s\".\n",
6694 type->name, baseType->name);
6695 return (1);
6696 }
6697 }
6698 }
6699
Daniel Veillard3646d642004-06-02 19:19:14 +00006700 /*
6701 * Gather attribute uses defined by this type.
6702 */
6703 if (attrs != NULL) {
6704 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
6705 &uses, &lastUse) == -1) {
6706 return (-1);
6707 }
6708 }
6709 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
6710 * "Two distinct attribute declarations in the {attribute uses} must
6711 * not have identical {name}s and {target namespace}s."
6712 *
6713 * For "extension" this is done further down.
6714 */
6715 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
6716 cur = uses;
6717 while (cur != NULL) {
6718 tmp = cur->next;
6719 while (tmp != NULL) {
6720 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6721 xmlSchemaGetOnymousAttrName(tmp->attr))) &&
6722 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
6723 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
6724
6725 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
6726 "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
6727 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6728 break;
6729 }
6730 tmp = tmp->next;
6731 }
6732 cur = cur->next;
6733 }
6734 }
6735 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
6736 /*
6737 * Derive by restriction.
6738 */
6739 if (baseIsAnyType) {
6740 type->attributeUses = uses;
6741 } else {
6742 int found;
6743
6744 cur = uses;
6745 while (cur != NULL) {
6746 found = 0;
6747 base = type->attributeUses;
6748 while (base != NULL) {
6749 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6750 xmlSchemaGetOnymousAttrName(base->attr))) &&
6751 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr),
6752 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) base->attr)))) {
6753
6754 found = 1;
6755 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6756 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6757 /*
6758 * derivation-ok-restriction 2.1.1
6759 */
6760 xmlSchemaPErr(ctxt, cur->attr->node,
6761 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
6762 "derivation-ok-restriction.2.1.1: "
6763 "The \"optional\" attribute "
6764 "use \"%s\" is inconsistent with a matching "
6765 "\"required\" attribute use of the base type\n",
6766 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6767 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
6768 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6769 /*
6770 * derivation-ok-restriction 3
6771 */
6772 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
6773 "derivation-ok-restriction.3: "
6774 "The \"required\" attribute use \"%s\" of the base type "
6775 "does not have a matching attribute use in the derived type\n",
6776 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6777
6778 } else {
6779 /*
6780 * Override the attribute use.
6781 */
6782 base->attr = cur->attr;
6783 }
6784 /*
6785 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
Daniel Veillard50355f02004-06-08 17:52:16 +00006786 * TODO: derivation-ok-restriction 2.1.3
Daniel Veillard3646d642004-06-02 19:19:14 +00006787 */
6788 break;
6789 }
6790 base = base->next;
6791 }
6792
6793 if (!found) {
6794 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6795 /*
6796 * derivation-ok-restriction 2.2
6797 */
6798 if ((type->attributeWildcard != NULL) &&
6799 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
6800 cur->attr->targetNamespace))
6801 found = 1;
6802
6803 if (!found) {
6804 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
6805 "derivation-ok-restriction.2.2: "
6806 "The attribute use \"%s\" has neither a matching attribute use, "
6807 "nor a matching wildcard in the base type\n",
6808 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6809 } else {
6810 /*
6811 * Add the attribute use.
6812 *
6813 * Note that this may lead to funny derivation error reports, if
6814 * multiple equal attribute uses exist; but this is not
6815 * allowed anyway, and it will be reported beforehand.
6816 */
6817 tmp = cur;
6818 if (prev != NULL)
6819 prev->next = cur->next;
6820 else
6821 uses = cur->next;
6822 cur = cur->next;
6823 if (type->attributeUses == NULL) {
6824 type->attributeUses = tmp;
6825 } else
6826 lastBaseUse->next = tmp;
6827 lastBaseUse = tmp;
6828
6829 continue;
6830 }
6831 }
6832 }
6833 prev = cur;
6834 cur = cur->next;
6835 }
6836 if (uses != NULL)
6837 xmlSchemaFreeAttributeUseList(uses);
6838 }
6839 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
6840 /*
6841 * The spec allows only appending, and not other kinds of extensions.
6842 *
6843 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
6844 */
6845 if (uses != NULL) {
6846 if (type->attributeUses == NULL) {
6847 type->attributeUses = uses;
6848 } else
6849 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00006850 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006851 } else {
6852 /*
Daniel Veillard50355f02004-06-08 17:52:16 +00006853 * Derive implicitely from the ur-type.
6854 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006855 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00006856 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006857 /*
6858 * 3.4.6 -> Complex Type Definition Properties Correct
6859 */
6860 if (type->attributeUses != NULL) {
6861 cur = type->attributeUses;
6862 prev = NULL;
6863 while (cur != NULL) {
6864 /*
6865 * 4. Two distinct attribute declarations in the {attribute uses} must
6866 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +00006867 *
Daniel Veillard3646d642004-06-02 19:19:14 +00006868 * Note that this was already done for "restriction" and types derived from
6869 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +00006870 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006871 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
6872 tmp = cur->next;
6873 while (tmp != NULL) {
6874 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6875 xmlSchemaGetOnymousAttrName(tmp->attr))) &&
6876 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
6877 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
6878
6879 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
6880 "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
6881 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00006882 break;
6883 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006884 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00006885 }
6886 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006887 /*
6888 * 5. Two distinct attribute declarations in the {attribute uses} must
6889 * not have {type definition}s which are or are derived from ID.
6890 */
6891 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00006892 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006893 if (id != NULL) {
6894 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_5,
6895 "ct-props-correct.5: Two attribute declarations, "
6896 "\"%s\" and \"%s\" have types which derived from ID\n",
6897 xmlSchemaGetOnymousAttrName(id->attr),
6898 xmlSchemaGetOnymousAttrName(cur->attr));
Daniel Veillard50355f02004-06-08 17:52:16 +00006899 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006900 id = cur;
6901 }
6902 /*
6903 * Remove "prohibited" attribute uses. The reason this is done at this late
6904 * stage is to be able to catch dublicate attribute uses. So we had to keep
6905 * prohibited uses in the list as well.
6906 */
6907 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6908 tmp = cur;
6909 if (prev == NULL)
6910 type->attributeUses = cur->next;
6911 else
6912 prev->next = cur->next;
6913 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00006914 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +00006915 } else {
6916 prev = cur;
6917 cur = cur->next;
6918 }
6919 }
6920 }
6921 /*
6922 * TODO: This check should be removed if we are 100% sure of
6923 * the base type attribute uses already being built.
6924 */
6925 if ((baseType != NULL) && (!baseIsAnyType) &&
6926 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
6927 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
6928 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00006929 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +00006930 "attribute uses not builded on base type \"%s\".\n",
6931 baseType->name, NULL);
6932 }
6933 return (0);
6934}
6935
6936/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00006937 * xmlSchemaTypeFinalContains:
6938 * @schema: the schema
6939 * @type: the type definition
6940 * @final: the final
6941 *
6942 * Evaluates if a type definition contains the given "final".
6943 * This does take "finalDefault" into account as well.
6944 *
6945 * Returns 1 if the type does containt the given "final",
6946 * 0 otherwise.
6947 */
6948static int
6949xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
6950{
6951 int tfinal = final, tflags = type->flags;
6952
6953 if (type == NULL)
6954 return (0);
6955 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
6956 switch (final) {
6957 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
6958 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6959 break;
6960 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
6961 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6962 break;
6963 case XML_SCHEMAS_TYPE_FINAL_LIST:
6964 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
6965 break;
6966 case XML_SCHEMAS_TYPE_FINAL_UNION:
6967 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
6968 break;
6969 }
6970 tflags = schema->flags;
6971 }
6972 if (tflags & tfinal)
6973 return (1);
6974 else
6975 return (0);
6976
6977}
6978
6979/**
6980 * xmlSchemaGetUnionSimpleTypeMemberTypes:
6981 * @type: the Union Simple Type
6982 *
6983 * Returns a list of member types of @type if existing,
6984 * returns NULL otherwise.
6985 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006986static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +00006987xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
6988{
6989 while (type != NULL) {
6990 if (type->memberTypes != NULL)
6991 return (type->memberTypes);
6992 else
6993 type = type->baseType;
6994 }
6995 return (NULL);
6996}
6997
6998/**
6999 * xmlSchemaGetListSimpleTypeItemType:
7000 * @type: the simple type definition
7001 *
7002 * Returns the item type definition of the list simple type.
7003 */
7004static xmlSchemaTypePtr
7005xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
7006{
7007 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
7008 return (NULL);
7009 /*
7010 * Note: In libxml2, the built-in types do not reflect
7011 * the datatype hierarchy (yet?) - we have to treat them
7012 * in a special way.
7013 */
7014 if (type->type == XML_SCHEMA_TYPE_BASIC)
7015 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
7016 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
7017 /* 1 If the <list> alternative is chosen, then the type
7018 * definition ·resolved· to by the ·actual value· of the
7019 * itemType [attribute] of <list>, if present, otherwise
7020 * the type definition corresponding to the <simpleType>
7021 * among the [children] of <list>.
7022 */
7023 return (type->subtypes->subtypes);
7024 else {
7025 /* 2 If the <restriction> option is chosen, then the
7026 * {item type definition} of the {base type definition}.
7027 */
7028 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
7029 }
7030}
7031
7032/**
7033 * xmlSchemaCheckCOSSTDerivedOK:
7034 * @type: the derived simple type definition
7035 * @baseType: the base type definition
7036 *
7037 * Checks wheter @type can be validly
7038 * derived from @baseType.
7039 *
7040 * Returns 0 on success, an positive error code otherwise.
7041 */
7042static int
7043xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
7044 xmlSchemaTypePtr type,
7045 xmlSchemaTypePtr baseType,
7046 int subset)
7047{
7048 /*
7049 * Schema Component Constraint: Type Derivation OK (Simple)
7050 *
7051 *
7052 * 1 They are the same type definition.
7053 * TODO: The identy check might have to be more complex than this.
7054 */
7055 if (type == baseType)
7056 return (0);
7057 /*
7058 * 2.1 restriction is not in the subset, or in the {final}
7059 * of its own {base type definition};
7060 */
7061 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
7062 (xmlSchemaTypeFinalContains(schema,
7063 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
7064 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
7065 }
7066 /* 2.2 */
7067 if (type->baseType == baseType) {
7068 /*
7069 * 2.2.1 D's ·base type definition· is B.
7070 */
7071 return (0);
7072 }
7073 /*
7074 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
7075 * and is validly derived from B given the subset, as defined by this
7076 * constraint.
7077 */
7078 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
7079 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
7080 return (0);
7081 }
7082 /*
7083 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
7084 * definition·.
7085 */
7086 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
7087 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
7088 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
7089 return (0);
7090 }
7091 /*
7092 * 2.2.4 B's {variety} is union and D is validly derived from a type
7093 * definition in B's {member type definitions} given the subset, as
7094 * defined by this constraint.
7095 *
7096 * NOTE: This seems not to involve built-in types, since there is no
7097 * built-in Union Simple Type.
7098 */
7099 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
7100 xmlSchemaTypeLinkPtr cur;
7101
7102 cur = baseType->memberTypes;
7103 while (cur != NULL) {
7104 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
7105 cur->type, subset) == 0)
7106 return (0);
7107 cur = cur->next;
7108 }
7109 }
7110
7111 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
7112}
7113
7114
7115/**
7116 * xmlSchemaCheckSTPropsCorrect:
7117 * @ctxt: the schema parser context
7118 * @type: the simple type definition
7119 *
7120 * Checks st-props-correct.
7121 *
7122 * Returns 0 if the properties are correct,
7123 * if not, a positive error code and -1 on internal
7124 * errors.
7125 */
7126static int
7127xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
7128 xmlSchemaTypePtr type)
7129{
7130 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
7131 anyType;
7132
7133 /*
7134 * Schema Component Constraint: Simple Type Definition Properties Correct
7135 *
7136 * NOTE: This is somehow redundant, since we actually built a simple type
7137 * to have all the needed information; this acts as an self test.
7138 */
7139 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
7140 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
7141 /*
7142 * TODO: 1 The values of the properties of a simple type definition must be as
7143 * described in the property tableau in Datatype definition, modulo the
7144 * impact of Missing Sub-components (§5.3).
7145 */
7146 /* Base type: If the datatype has been ·derived· by ·restriction·
7147 * then the Simple Type Definition component from which it is ·derived·,
7148 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
7149 */
7150 if (baseType == NULL) {
7151 xmlSchemaPErr(ctxt, type->node,
7152 XML_SCHEMAP_ST_PROPS_CORRECT_1,
7153 "Simple type \"%s\" does not have a base type.\n",
7154 type->name, NULL);
7155 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
7156 }
7157 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
7158 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
7159 (baseType == anyType))) {
7160 xmlSchemaPErr(ctxt, type->node,
7161 XML_SCHEMAP_ST_PROPS_CORRECT_1,
7162 "Simple type \"%s\": its base type \"%s\" is not a simple "
7163 "type.\n",
7164 type->name, baseType->name);
7165 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
7166 }
7167 if ((baseType != anySimpleType) &&
7168 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
7169 xmlSchemaPErr(ctxt, type->node,
7170 XML_SCHEMAP_ST_PROPS_CORRECT_1,
7171 "Simple type \"%s\" (not derived by restriction) must have"
7172 "the simple ur-type definition as base type, not \"%s\".\n",
7173 type->name, NULL);
7174 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
7175 }
7176 /*
7177 * Variety: One of {atomic, list, union}.
7178 */
7179 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
7180 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
7181 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
7182 xmlSchemaPErr(ctxt, type->node,
7183 XML_SCHEMAP_ST_PROPS_CORRECT_1,
7184 "Simple type \"%s\" has an absent variety.\n",
7185 type->name, NULL);
7186 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
7187 }
7188 /* TODO: Finish this. */
7189
7190 /*
7191 * 2 All simple type definitions must be derived ultimately from the ·simple
7192 * ur-type definition (so· circular definitions are disallowed). That is, it
7193 * must be possible to reach a built-in primitive datatype or the ·simple
7194 * ur-type definition· by repeatedly following the {base type definition}.
7195 */
7196 baseType = type->baseType;
7197 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
7198 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
7199 xmlSchemaTypeFixup(baseType, ctxt, NULL);
7200 if (baseType == anySimpleType)
7201 break;
7202 else if (baseType == type) {
7203 xmlSchemaPErr(ctxt, type->node,
7204 XML_SCHEMAP_ST_PROPS_CORRECT_2,
7205 "Simple type \"%s\" is not derived from the simple "
7206 "ur-type definition (circular definitions are disallowed).\n",
7207 type->name, NULL);
7208 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
7209 }
7210 baseType = baseType->baseType;
7211 }
7212 /*
7213 * 3 The {final} of the {base type definition} must not contain restriction.
7214 */
7215 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
7216 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
7217 xmlSchemaPErr(ctxt, type->node,
7218 XML_SCHEMAP_ST_PROPS_CORRECT_3,
7219 "Simple type \"%s\": the \"final\" of its base type "
7220 "\"%s\" must not contain \"restriction\".\n",
7221 type->name, baseType->name);
7222 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
7223 }
7224 return (0);
7225}
7226
7227/**
7228 * xmlSchemaCheckDerivationValidSimpleRestriction:
7229 * @ctxt: the schema parser context
7230 * @type: the simple type definition
7231 *
7232 * Checks if the given @type (simpleType) is derived
7233 * validly by restriction.
7234 *
7235 * Returns -1 on internal errors, 0 if the type is validly derived,
7236 * a positive error code otherwise.
7237 */
7238static int
7239xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
7240 xmlSchemaTypePtr type)
7241{
7242
7243 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
7244 xmlSchemaPErr(ctxt, type->node,
7245 XML_ERR_INTERNAL_ERROR,
7246 "xmlSchemaCheckDerivationValidSimpleRestriction: the given "
7247 "type \"%s\" is not a user-derived simpleType.\n",
7248 type->name, NULL);
7249 return (-1);
7250 }
7251
7252 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
7253 xmlSchemaTypePtr primitive;
7254 /*
7255 * 1.1 The {base type definition} must be an atomic simple
7256 * type definition or a built-in primitive datatype.
7257 */
7258 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
7259 xmlSchemaPErr(ctxt, type->node,
7260 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
7261 "Atomic simple type \"%s\": "
7262 "its base type \"%s\" is not an atomic simple type.\n",
7263 type->name, NULL);
7264 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
7265 }
7266 /* 1.2 The {final} of the {base type definition} must not contain
7267 * restriction.
7268 */
7269 /* OPTIMIZE: This is already done in xmlSchemaCheckStPropsCorrect */
7270 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
7271 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
7272 xmlSchemaPErr(ctxt, type->node,
7273 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
7274 "Atomic simple type \"%s\": the \"final\" of its base type "
7275 "\"%s\" must not contain \"restriction\".\n",
7276 type->name, type->baseType->name);
7277 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
7278 }
7279
7280 /*
7281 * 1.3.1 DF must be an allowed constraining facet for the {primitive
7282 * type definition}, as specified in the appropriate subsection of 3.2
7283 * Primitive datatypes.
7284 */
7285 if (type->facets != NULL) {
7286 xmlSchemaFacetPtr facet;
7287 int ok = 1;
7288
7289 primitive = xmlSchemaGetPrimitiveType(type);
7290 if (primitive == NULL) {
7291 xmlSchemaPErr(ctxt, type->node,
7292 XML_ERR_INTERNAL_ERROR,
7293 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
7294 "to get primitive type of type \"%s\".\n",
7295 type->name, NULL);
7296 return (-1);
7297 }
7298 facet = type->facets;
7299 do {
7300 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
7301 xmlSchemaPErrExt(ctxt, type->node,
7302 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
7303 NULL, NULL, NULL,
7304 "Atomic simple type \"%s\": the facet \"%s\" "
7305 "is not allowed on primitive type \"%s\".\n",
7306 type->name,
William M. Brack96d2eff2004-06-30 11:48:47 +00007307 (const xmlChar *)
Daniel Veillard01fa6152004-06-29 17:04:39 +00007308 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007309 BAD_CAST primitive->name, NULL, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007310
7311 ok = 0;
7312 }
7313 facet = facet->next;
7314 } while (facet != NULL);
7315 if (ok == 0)
7316 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
7317
7318 }
7319 /*
7320 * TODO: 1.3.2 (facet derivation)
7321 */
7322 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
7323 xmlSchemaTypePtr itemType = NULL;
7324
7325 itemType = xmlSchemaGetListSimpleTypeItemType(type);
7326 if (itemType == NULL) {
7327 xmlSchemaPErr(ctxt, type->node,
7328 XML_ERR_INTERNAL_ERROR,
7329 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
7330 "failed to evaluate the item type of type \"%s\".\n",
7331 type->name, NULL);
7332 return (-1);
7333 }
7334 /*
7335 * 2.1 The {item type definition} must have a {variety} of atomic or
7336 * union (in which case all the {member type definitions}
7337 * must be atomic).
7338 */
7339 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
7340 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
7341 xmlSchemaPErr(ctxt, type->node,
7342 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
7343 "List simple type \"%s\": its item type \"%s\" "
7344 "is not an atomic or union simple type.\n",
7345 type->name, itemType->name);
7346 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
7347 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
7348 xmlSchemaTypeLinkPtr member;
7349
7350 member = itemType->memberTypes;
7351 while (member != NULL) {
7352 if ((member->type->flags &
7353 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
7354 xmlSchemaPErr(ctxt, type->node,
7355 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
7356 "List simple type \"%s\": its item type "
7357 "is a union simple type, but the member type "
7358 "\"%s\" of this item type is not an \"atomic\" "
7359 "simple type.\n",
7360 type->name, member->type->name);
7361 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
7362 }
7363 member = member->next;
7364 }
7365 }
7366
7367 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
7368 xmlSchemaFacetPtr facet;
7369 /*
7370 * This is the case if we have: <simpleType><list ..
7371 */
7372 /*
7373 * 2.3.1
7374 * 2.3.1.1 The {final} of the {item type definition} must not
7375 * contain list.
7376 */
7377 if (xmlSchemaTypeFinalContains(ctxt->schema,
7378 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
7379 xmlSchemaPErr(ctxt, type->node,
7380 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
7381 "List simple type \"%s\": the \"final\" of its item type "
7382 "\"%s\" must not contain \"list\".\n",
7383 type->name, itemType->name);
7384 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
7385 }
7386 /*
7387 * 2.3.1.2 The {facets} must only contain the whiteSpace
7388 * facet component.
7389 */
7390 if (type->facets != NULL) {
7391 facet = type->facets;
7392 do {
7393 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
7394 xmlSchemaPErr(ctxt, type->node,
7395 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
7396 "List simple type \"%s\": the facet \"%s\" "
7397 "is not allowed.\n",
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007398 type->name,
7399 BAD_CAST xmlSchemaFacetTypeToString(facet->type));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007400 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
7401 }
7402 facet = facet->next;
7403 } while (facet != NULL);
7404 }
7405 /*
7406 * TODO: Datatypes states:
7407 * A ·list· datatype can be ·derived· from an ·atomic· datatype
7408 * whose ·lexical space· allows space (such as string or anyURI)or
7409 * a ·union· datatype any of whose {member type definitions}'s
7410 * ·lexical space· allows space.
7411 */
7412 } else {
7413 /*
7414 * This is the case if we have: <simpleType><restriction ...
7415 */
7416 /*
7417 * 2.3.2
7418 * 2.3.2.1 The {base type definition} must have a {variety} of list.
7419 */
7420 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
7421 xmlSchemaPErr(ctxt, type->node,
7422 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
7423 "List simple type \"%s\": its base type \"%s\" must "
7424 "have a variety of list.\n",
7425 type->name, type->baseType->name);
7426 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
7427 }
7428 /*
7429 * 2.3.2.2 The {final} of the {base type definition} must not
7430 * contain restriction.
7431 */
7432 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
7433 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
7434 xmlSchemaPErr(ctxt, type->node,
7435 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
7436 "List simple type \"%s\": its base type \"%s\" must not "
7437 "have a \"final\" containing \"restriction\".\n",
7438 type->name, type->baseType->name);
7439 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
7440 }
7441 /*
7442 * 2.3.2.3 The {item type definition} must be validly derived
7443 * from the {base type definition}'s {item type definition} given
7444 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
7445 */
7446 {
7447 xmlSchemaTypePtr baseItemType;
7448
7449 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
7450 if (baseItemType == NULL) {
7451 xmlSchemaPErr(ctxt, type->node,
7452 XML_ERR_INTERNAL_ERROR,
7453 "xmlSchemaCheckDerivationValidSimpleRestriction: "
7454 "List simple type \"%s\": failed to "
7455 "evaluate the item type of its base type \"%s\".\n",
7456 type->name, type->baseType->name);
7457 return (-1);
7458 }
7459 if ((itemType != baseItemType) &&
7460 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
7461 baseItemType, 0) != 0)) {
7462 xmlSchemaPErrExt(ctxt, type->node,
7463 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3, NULL, NULL, NULL,
7464 "List simple type \"%s\": its item type \"%s\" is not "
7465 "validly derived from the item type \"%s\" of the "
7466 "base type \"%s\" as defined in Type Derivation OK "
7467 "(Simple).\n",
7468 type->name, itemType->name, baseItemType->name,
7469 type->baseType->name, NULL);
7470 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
7471 }
7472 }
7473
7474 if (type->facets != NULL) {
7475 xmlSchemaFacetPtr facet;
7476 int ok = 1;
7477 /*
7478 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
7479 * and enumeration facet components are allowed among the {facets}.
7480 */
7481 facet = type->facets;
7482 do {
7483 switch (facet->type) {
7484 case XML_SCHEMA_FACET_LENGTH:
7485 case XML_SCHEMA_FACET_MINLENGTH:
7486 case XML_SCHEMA_FACET_MAXLENGTH:
7487 case XML_SCHEMA_FACET_WHITESPACE:
7488 /*
7489 * TODO: 2.5.1.2 List datatypes
7490 * The value of ·whiteSpace· is fixed to the value collapse.
7491 */
7492 case XML_SCHEMA_FACET_PATTERN:
7493 case XML_SCHEMA_FACET_ENUMERATION:
7494 break;
7495 default: {
7496 xmlSchemaPErr(ctxt, type->node,
7497 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
7498 "List simple type \"%s\": the facet \"%s\" "
7499 "is not allowed.\n",
7500 type->name,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007501 BAD_CAST xmlSchemaFacetTypeToString(facet->type));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007502 /*
7503 * We could return, but it's nicer to report all
7504 * invalid facets.
7505 */
7506 ok = 0;
7507 }
7508 }
7509 facet = facet->next;
7510 } while (facet != NULL);
7511 if (ok == 0)
7512 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
7513 /*
7514 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
7515 * is a facet of the same kind in the {facets} of the {base type
7516 * definition} (call this BF),then the DF's {value} must be a valid
7517 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
7518 */
7519 }
7520
7521
7522 }
7523 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
7524 /*
7525 * 3.1 The {member type definitions} must all have {variety} of
7526 * atomic or list.
7527 */
7528 xmlSchemaTypeLinkPtr member;
7529
7530 member = type->memberTypes;
7531 while (member != NULL) {
7532 if (((member->type->flags &
7533 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
7534 ((member->type->flags &
7535 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
7536 xmlSchemaPErr(ctxt, type->node,
7537 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
7538 "Union simple type \"%s\": the member type "
7539 "\"%s\" is not an \"atomic\" simple type.\n",
7540 type->name, member->type->name);
7541 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
7542 }
7543 member = member->next;
7544 }
7545 /*
7546 * 3.3.1 If the {base type definition} is the ·simple ur-type
7547 * definition·
7548 */
7549 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
7550 /*
7551 * 3.3.1.1 All of the {member type definitions} must have a
7552 * {final} which does not contain union.
7553 */
7554 member = type->memberTypes;
7555 while (member != NULL) {
7556 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
7557 XML_SCHEMAS_TYPE_FINAL_UNION)) {
7558 xmlSchemaPErr(ctxt, type->node,
7559 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
7560 "Union simple type \"%s\": the \"final\" of member type "
7561 "\"%s\" contains \"union\".\n",
7562 type->name, member->type->name);
7563 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
7564 }
7565 member = member->next;
7566 }
7567 /*
7568 * 3.3.1.2 The {facets} must be empty.
7569 */
7570 if (type->facetSet != NULL) {
7571 xmlSchemaPErr(ctxt, type->node,
7572 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
7573 "Union simple type \"%s\": the facets must be empty.\n",
7574 type->name, NULL);
7575 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
7576 }
7577 } else {
7578 /*
7579 * 3.3.2.1 The {base type definition} must have a {variety} of union.
7580 */
7581 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
7582 xmlSchemaPErr(ctxt, type->node,
7583 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
7584 "Union simple type \"%s\": its base type \"%s\" has not a "
7585 "variety of union.\n",
7586 type->name, type->baseType->name);
7587 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
7588 }
7589 /*
7590 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
7591 */
7592 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
7593 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
7594 xmlSchemaPErr(ctxt, type->node,
7595 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
7596 "Union simple type \"%s\": the \"final\" of its base "
7597 "type \"%s\" must not contain \"restriction\".\n",
7598 type->name, type->baseType->name);
7599 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
7600 }
7601 /*
7602 * 3.3.2.3 The {member type definitions}, in order, must be validly
7603 * derived from the corresponding type definitions in the {base
7604 * type definition}'s {member type definitions} given the empty set,
7605 * as defined in Type Derivation OK (Simple) (§3.14.6).
7606 */
7607 {
7608 xmlSchemaTypeLinkPtr baseMember;
7609
7610 /*
7611 * OPTIMIZE: if the type is restricting, it has no local defined
7612 * member types and inherits the member types of the base type;
7613 * thus a check for equality can be skipped.
7614 */
7615 /*
7616 * TODO: Even worse: I cannot see a scenario where a restricting
7617 * union simple type can have other member types as the member
7618 * types of it's base type. This check seems not necessary with
7619 * respect to the derivation process in libxml2.
7620 */
7621 if (type->memberTypes != NULL) {
7622 member = type->memberTypes;
7623 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
7624 if ((member == NULL) && (baseMember != NULL)) {
7625 xmlSchemaPErr(ctxt, type->node,
7626 XML_SCHEMAS_ERR_INTERNAL,
7627 "Internal error: "
7628 "xmlSchemaCheckDerivationValidSimpleRestriction "
7629 "(3.3.2.3), union simple type \"%s\", unequal number "
7630 "of member types in the base type\n",
7631 type->name, NULL);
7632 }
7633 while (member != NULL) {
7634 if (baseMember == NULL) {
7635 xmlSchemaPErr(ctxt, type->node,
7636 XML_SCHEMAS_ERR_INTERNAL,
7637 "Internal error: "
7638 "xmlSchemaCheckDerivationValidSimpleRestriction "
7639 "(3.3.2.3), union simple type \"%s\", unequal number "
7640 "of member types in the base type\n",
7641 type->name, NULL);
7642 }
7643 if ((member->type != baseMember->type) &&
7644 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
7645 member->type, baseMember->type, 0) != 0)) {
7646 xmlSchemaPErrExt(ctxt, type->node,
7647 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3, NULL,
7648 NULL, NULL,
7649 "Union simple type \"%s\": its member type "
7650 "\"%s\" is not validly derived from its "
7651 "corresponding member type \"%s\" of the base "
7652 "type \"%s\" as defined in Type Derivation OK "
7653 "(Simple).\n",
7654 type->name, member->type->name,
7655 baseMember->type->name,
7656 type->baseType->name, NULL);
7657 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
7658 }
7659 member = member->next;
7660 baseMember = baseMember->next;
7661 }
7662 }
7663 }
7664 /*
7665 * 3.3.2.4 Only pattern and enumeration facet components are
7666 * allowed among the {facets}.
7667 */
7668 if (type->facets != NULL) {
7669 xmlSchemaFacetPtr facet;
7670 int ok = 1;
7671
7672 facet = type->facets;
7673 do {
7674 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
7675 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
7676 xmlSchemaPErr(ctxt, type->node,
7677 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
7678 "Union simple type \"%s\": the facet \"%s\" "
7679 "is not allowed.\n",
7680 type->name,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007681 BAD_CAST xmlSchemaFacetTypeToString(facet->type));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007682 ok = 0;
7683 }
7684 facet = facet->next;
7685 } while (facet != NULL);
7686 if (ok == 0)
7687 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
7688
7689 }
7690 /*
7691 * TODO: 3.3.2.5 (facet derivation)
7692 */
7693 }
7694 }
7695
7696 return (0);
7697}
7698
7699/**
7700 * xmlSchemaCheckSRCSimpleType:
7701 * @ctxt: the schema parser context
7702 * @type: the simple type definition
7703 *
7704 * Checks crc-simple-type constraints.
7705 *
7706 * Returns 0 if the constraints are satisfied,
7707 * if not a positive error code and -1 on internal
7708 * errors.
7709 */
7710static int
7711xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
7712 xmlSchemaTypePtr type)
7713{
7714 /*
7715 * NOTE: src-simple-type 2-4 are redundant, since the checks
7716 * were are done for the corresponding <restriction>, <list> and <union>
7717 * elements, but W3C wants a <simpleType> error as well, so it gets one.
7718 * Maby this can be skipped in the future, if we get sure it's not needed.
7719 */
7720 if (type->subtypes == NULL) {
7721 xmlSchemaPErr(ctxt, type->node,
7722 XML_SCHEMAS_ERR_INTERNAL,
7723 "Internal error: xmlSchemaCheckSRCSimpleType, "
7724 "no subtype on simple type \"%s\".\n",
7725 type->name, NULL);
7726 return (-1);
7727 }
7728 /*
7729 * src-simple-type.1 The corresponding simple type definition, if any,
7730 * must satisfy the conditions set out in Constraints on Simple Type
7731 * Definition Schema Components (§3.14.6).
7732 */
7733 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
7734 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
7735 /*
7736 * TODO: Removed this, since it got annoying to get an
7737 * extra error report, if anything failed until now.
7738 * Enable this if needed.
7739 */
7740 /*
7741 xmlSchemaPErr(ctxt, type->node,
7742 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
7743 "Simple type \"%s\" does not satisfy the constraints "
7744 "on simple type definitions.\n",
7745 type->name, NULL);
7746 */
7747 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
7748 }
7749
7750 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
7751 /*
7752 * src-simple-type.2 If the <restriction> alternative is chosen,
7753 * either it must have a base [attribute] or a <simpleType> among its
7754 * [children], but not both.
7755 */
7756 if (((type->subtypes->base == NULL) &&
7757 ((type->subtypes->subtypes == NULL) ||
7758 (type->subtypes->subtypes->type != XML_SCHEMA_TYPE_SIMPLE))) ||
7759 ((type->subtypes->base != NULL) &&
7760 (type->subtypes->subtypes != NULL) &&
7761 (type->subtypes->subtypes->type == XML_SCHEMA_TYPE_SIMPLE))) {
7762 xmlSchemaPErr(ctxt, type->node,
7763 XML_SCHEMAP_SRC_SIMPLE_TYPE_2,
7764 "Simple type \"%s\": "
7765 "The <restriction> alternative is chosen, thus either the "
7766 "\"base\" attribute or the <simpleType> child "
7767 "must be present, but not both.\n",
7768 type->name, NULL);
7769 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_2);
7770 }
7771 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
7772 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
7773 * an itemType [attribute] or a <simpleType> among its [children],
7774 * but not both.
7775 * NOTE: baseType is set to the local simple type definiton,
7776 * if existent, at parse time. This is a hack and not nice.
7777 */
7778 if (((type->subtypes->base == NULL) &&
7779 (type->baseType == NULL)) ||
7780 ((type->subtypes->base != NULL) &&
7781 (type->subtypes->baseType != NULL))) {
7782 xmlSchemaPErr(ctxt, type->node,
7783 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
7784 "Simple type \"%s\": "
7785 "The <list> alternative is chosen, thus either the "
7786 "\"itemType\" attribute or the <simpleType> child "
7787 "must be present, but not both.\n",
7788 type->name, NULL);
7789 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
7790 }
7791
7792
7793 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
7794 xmlSchemaTypeLinkPtr member;
7795 xmlSchemaTypePtr ancestor, anySimpleType;
7796
7797 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
7798
7799 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
7800 * the <union> alternative is chosen, there must not be any entries
7801 * in the memberTypes [attribute] at any depth which resolve to the
7802 * component corresponding to the <simpleType>.
7803 */
7804 member = type->memberTypes;
7805 while (member != NULL) {
7806 ancestor = member->type;
7807 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
7808 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
7809 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
7810 if (ancestor == anySimpleType)
7811 break;
7812 else if (ancestor == type) {
7813 xmlSchemaPErr(ctxt, type->node,
7814 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
7815 "Simple type \"%s\" is not derived from the simple "
7816 "ur-type definition (circular definitions are disallowed).\n",
7817 type->name, NULL);
7818 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
7819 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
7820 /*
7821 * TODO: Although a list simple type must not have a union ST
7822 * type as item type, which in turn has a list ST as member
7823 * type, we will assume this here as well, since this check
7824 * was not yet performed.
7825 */
7826
7827 }
7828 ancestor = ancestor->baseType;
7829 }
7830 member = member->next;
7831 }
7832
7833 }
7834
7835 return (0);
7836}
7837
7838/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007839 * xmlSchemaTypeFixup:
7840 * @typeDecl: the schema type definition
7841 * @ctxt: the schema parser context
7842 *
7843 * Fixes the content model of the type.
7844 */
7845static void
7846xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007847 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00007848{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007849 xmlSchemaTypePtr ctxtType;
7850
Daniel Veillard82bbbd42003-05-11 20:16:09 +00007851 if (typeDecl == NULL)
7852 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007853 /*
7854 * Do not allow the following types to be typefixed, prior to
7855 * the corresponding simple/complex types.
7856 */
7857 if (ctxt->ctxtType == NULL) {
7858 switch (typeDecl->type) {
7859 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
7860 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
7861 case XML_SCHEMA_TYPE_UNION:
7862 case XML_SCHEMA_TYPE_RESTRICTION:
7863 case XML_SCHEMA_TYPE_EXTENSION:
7864 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007865 default:
7866 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007867 }
7868 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007869 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007870 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007871 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007872 switch (typeDecl->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007873 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
7874 if (typeDecl->subtypes != NULL) {
7875 if (typeDecl->subtypes->contentType ==
7876 XML_SCHEMA_CONTENT_UNKNOWN) {
7877 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
7878 NULL);
7879 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007880 typeDecl->contentType =
7881 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007882 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007883 break;
7884 }
7885 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007886 xmlSchemaTypePtr base = NULL;
7887
7888 ctxt->ctxtType->flags |=
7889 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007890 if (typeDecl->subtypes != NULL)
7891 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007892
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007893 if (typeDecl->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007894 base =
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007895 xmlSchemaGetType(ctxt->schema, typeDecl->base,
7896 typeDecl->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007897 if (base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007898 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00007899 XML_SCHEMAP_SRC_RESOLVE,
7900 "Restriction \"%s\": the QName \"%s\" of the "
7901 "attribute \"base\" does not resolve to a schema "
7902 "component.\n",
7903 name, typeDecl->base);
7904 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +00007905 XML_SCHEMA_CONTENT_UNKNOWN) {
7906 /*
7907 * The base type might be not "type fixed" yet,
7908 * so do it now. */
7909 /*
7910 * TODO: Is a check for circular derivation already
7911 * done?
7912 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007913 xmlSchemaTypeFixup(base, ctxt, NULL);
7914 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007915 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007916 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
7917 /*
7918 * ComplexType restriction.
7919 */
7920 /*
7921 * Base type: The type definition ·resolved· to by the ·actual
7922 * value· of the base [attribute]
7923 */
7924 ctxt->ctxtType->baseType = base;
7925 /*
7926 * Content type.
7927 */
7928 if (typeDecl->subtypes == NULL)
7929 /* 1.1.1 */
7930 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
7931 else if ((typeDecl->subtypes->subtypes == NULL) &&
7932 ((typeDecl->subtypes->type ==
7933 XML_SCHEMA_TYPE_ALL)
7934 || (typeDecl->subtypes->type ==
7935 XML_SCHEMA_TYPE_SEQUENCE)))
7936 /* 1.1.2 */
7937 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
7938 else if ((typeDecl->subtypes->type ==
7939 XML_SCHEMA_TYPE_CHOICE)
7940 && (typeDecl->subtypes->subtypes == NULL))
7941 /* 1.1.3 */
7942 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
7943 else {
7944 /* 1.2 and 2.X are applied at the other layer */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007945 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +00007946 XML_SCHEMA_CONTENT_ELEMENTS;
7947 }
7948 } else {
7949 /*
7950 * SimpleType restriction.
7951 */
7952 /* Base type:
7953 * The Simple Type Definition component resolved to by
7954 * the actual value of the base [attribute] or the
7955 * <simpleType> [children], whichever is present.
7956 */
7957 if ((base == NULL) && (typeDecl->subtypes != NULL)) {
7958 base = typeDecl->subtypes;
7959 ctxt->ctxtType->baseType = base;
7960 if (base->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
7961 xmlSchemaTypeFixup(base, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007962 } else
Daniel Veillard01fa6152004-06-29 17:04:39 +00007963 ctxt->ctxtType->baseType = base;
7964
7965 if (((typeDecl->base == NULL) &&
7966 ((typeDecl->subtypes == NULL) ||
7967 (typeDecl->subtypes->type != XML_SCHEMA_TYPE_SIMPLE))) ||
7968 ((typeDecl->base != NULL) &&
7969 (typeDecl->subtypes != NULL) &&
7970 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SIMPLE))) {
7971 /*
7972 * src-restriction-base-or-simpleType
7973 * Either the base [attribute] or the simpleType [child] of the
7974 * <restriction> element must be present, but not both.
7975 */
7976 xmlSchemaPErr(ctxt, typeDecl->node,
7977 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7978 "Restriction \"%s\": "
7979 "Either the \"base\" attribute or the <simpleType> child "
7980 "must be present, but not both.\n",
7981 typeDecl->name, NULL);
7982 }
7983 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007984 break;
7985 }
7986 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007987 xmlSchemaTypePtr base = NULL;
7988 xmlSchemaContentType explicitContentType;
7989
7990 /*
7991 * An extension does exist on a complexType only.
7992 */
7993 ctxt->ctxtType->flags |=
7994 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
7995 if (typeDecl->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007996 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillard2582a332004-04-18 19:49:46 +00007997 xmlSchemaPErr(ctxt, typeDecl->node,
7998 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
7999 "Schemas: extension type %s is recursive\n",
8000 name, NULL);
8001 return;
8002 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008003 if (typeDecl->base != NULL) {
8004 base =
8005 xmlSchemaGetType(ctxt->schema, typeDecl->base,
8006 typeDecl->baseNs);
8007 if (base == NULL) {
8008 xmlSchemaPErr(ctxt, typeDecl->node,
8009 XML_SCHEMAP_SRC_RESOLVE,
8010 "Extension \"%s\": the QName \"%s\" of the "
8011 "attribute \"base\" does not resolve to a schema "
8012 "component.\n",
8013 name, typeDecl->base);
8014 } else if (base->contentType ==
8015 XML_SCHEMA_CONTENT_UNKNOWN) {
8016 typeDecl->recurse = 1;
8017 xmlSchemaTypeFixup(base, ctxt, NULL);
8018 typeDecl->recurse = 0;
8019 }
8020 /*
8021 * The type definition ·resolved· to by the ·actual
8022 * value· of the base [attribute]
8023 */
8024 ctxt->ctxtType->baseType = base;
8025 /*
8026 * TODO: This one is still needed for computation of
8027 * the content model by xmlSchemaBuildAContentModel.
8028 * Try to get rid of it.
8029 */
8030 typeDecl->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008031 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008032 if ((typeDecl->subtypes != NULL) &&
8033 (typeDecl->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
8034 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
8035
8036 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
8037 if (typeDecl->subtypes == NULL)
8038 /* 1.1.1 */
8039 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
8040 else if ((typeDecl->subtypes->subtypes == NULL) &&
8041 ((typeDecl->subtypes->type ==
8042 XML_SCHEMA_TYPE_ALL)
8043 || (typeDecl->subtypes->type ==
8044 XML_SCHEMA_TYPE_SEQUENCE)))
8045 /* 1.1.2 */
8046 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
8047 else if ((typeDecl->subtypes->type ==
8048 XML_SCHEMA_TYPE_CHOICE)
8049 && (typeDecl->subtypes->subtypes == NULL))
8050 /* 1.1.3 */
8051 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
8052 if (base != NULL) {
8053 /* It will be reported later, if the base is missing. */
8054 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
8055 /* 2.1 */
8056 typeDecl->contentType = base->contentType;
8057 } else if (base->contentType ==
8058 XML_SCHEMA_CONTENT_EMPTY) {
8059 /* 2.2 imbitable ! */
8060 typeDecl->contentType =
8061 XML_SCHEMA_CONTENT_ELEMENTS;
8062 } else {
8063 /* 2.3 imbitable pareil ! */
8064 typeDecl->contentType =
8065 XML_SCHEMA_CONTENT_ELEMENTS;
8066 }
8067 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008068 break;
8069 }
8070 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008071 ctxtType = ctxt->ctxtType;
8072 ctxt->ctxtType = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008073 if ((typeDecl->subtypes == NULL) ||
8074 ((typeDecl->subtypes->type !=
8075 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
8076 (typeDecl->subtypes->type !=
8077 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
8078 /*
8079 * This case is understood as shorthand for complex
8080 * content restricting the ur-type definition, and
8081 * the details of the mappings should be modified as
8082 * necessary.
8083 */
8084 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
8085 typeDecl->flags |=
8086 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
8087 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008088 if (typeDecl->subtypes == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008089 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00008090 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
8091 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +00008092 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008093 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008094 if ((typeDecl->subtypes != NULL) &&
8095 (typeDecl->subtypes->contentType ==
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008096 XML_SCHEMA_CONTENT_UNKNOWN)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008097 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008098 NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008099 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008100 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008101 typeDecl->contentType =
8102 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008103 } else {
8104 if (typeDecl->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008105 typeDecl->contentType =
8106 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008107 }
8108 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008109 }
8110 xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008111 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008112 break;
8113 }
8114 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
8115 if (typeDecl->subtypes == NULL) {
8116 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00008117 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
8118 typeDecl->contentType =
8119 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008120 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00008121 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008122 typeDecl->contentType =
8123 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +00008124 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008125 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
8126 NULL);
8127 if (typeDecl->subtypes != NULL)
8128 typeDecl->contentType =
8129 typeDecl->subtypes->contentType;
8130 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008131 /*
8132 * Removed due to implementation of the build of attribute uses.
8133 */
8134 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00008135 if (typeDecl->attributes == NULL)
8136 typeDecl->attributes =
8137 typeDecl->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +00008138 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008139 }
8140 break;
8141 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008142 case XML_SCHEMA_TYPE_SIMPLE:
8143 /*
8144 * Simple Type Definition Schema Component
8145 *
8146 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008147 ctxtType = ctxt->ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008148 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
8149 if (typeDecl->subtypes->contentType ==
8150 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008151 ctxt->ctxtType = typeDecl;
8152 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008153 }
8154 /* Fixup base type */
8155 if ((typeDecl->baseType != NULL) &&
8156 (typeDecl->baseType->contentType ==
8157 XML_SCHEMA_CONTENT_UNKNOWN)) {
8158 /* OPTIMIZE: Actually this one will never by hit, since
8159 * the base type is already type-fixed in <restriction>.
8160 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008161 ctxt->ctxtType = typeDecl;
8162 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008163 }
8164 /* Base type:
8165 * 2 If the <list> or <union> alternative is chosen,
8166 * then the ·simple ur-type definition·.
8167 */
8168 if (typeDecl->subtypes->type ==
8169 XML_SCHEMA_TYPE_LIST) {
8170 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8171 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
8172 } else if (typeDecl->subtypes->type ==
8173 XML_SCHEMA_TYPE_UNION) {
8174 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8175 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8176 } else if (typeDecl->subtypes->type ==
8177 XML_SCHEMA_TYPE_RESTRICTION) {
8178 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
8179
8180 /*
8181 * Variety
8182 * If the <restriction> alternative is chosen, then the
8183 * {variety} of the {base type definition}.
8184 */
8185 if (typeDecl->baseType != NULL) {
8186 if (typeDecl->baseType->flags &
8187 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
8188 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
8189 else if (typeDecl->baseType->flags &
8190 XML_SCHEMAS_TYPE_VARIETY_LIST)
8191 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
8192 else if (typeDecl->baseType->flags &
8193 XML_SCHEMAS_TYPE_VARIETY_UNION)
8194 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8195 /*
8196 * Schema Component Constraint: Simple Type Restriction
8197 * (Facets)
8198 * NOTE: Satisfaction of 1 and 2 arise from the fixup
8199 * applied beforehand.
8200 *
8201 * 3 The {facets} of R are the union of S and the {facets}
8202 * of B, eliminating duplicates. To eliminate duplicates,
8203 * when a facet of the same kind occurs in both S and the
8204 * {facets} of B, the one in the {facets} of B is not
8205 * included, with the exception of enumeration and pattern
8206 * facets, for which multiple occurrences with distinct values
8207 * are allowed.
8208 */
8209 if (typeDecl->baseType->facetSet != NULL) {
8210 last = typeDecl->facetSet;
8211 if (last != NULL)
8212 while (last->next != NULL)
8213 last = last->next;
8214 cur = typeDecl->baseType->facetSet;
8215 for (; cur != NULL; cur = cur->next) {
8216 /*
8217 * Base patterns won't be add here:
8218 * they are ORed in a type and
8219 * ANDed in derived types. This will
8220 * happed at validation level by
8221 * walking the base axis of the type.
8222 */
8223 if (cur->facet->type ==
8224 XML_SCHEMA_FACET_PATTERN)
8225 continue;
8226 facet = NULL;
8227 if ((typeDecl->facetSet != NULL) &&
8228 (cur->facet->type !=
8229 XML_SCHEMA_FACET_PATTERN) &&
8230 (cur->facet->type !=
8231 XML_SCHEMA_FACET_ENUMERATION)) {
8232 facet = typeDecl->facetSet;
8233 do {
8234 if (cur->facet->type ==
8235 facet->facet->type)
8236 break;
8237 facet = facet->next;
8238 } while (facet != NULL);
8239 }
8240 if (facet == NULL) {
8241 facet = (xmlSchemaFacetLinkPtr)
8242 xmlMalloc(sizeof(xmlSchemaFacetLink));
8243 if (facet == NULL) {
8244 xmlSchemaPErrMemory(ctxt,
8245 "fixing simpleType", NULL);
8246 return;
8247 }
8248 facet->facet = cur->facet;
8249 facet->next = NULL;
8250 if (last == NULL)
8251 typeDecl->facetSet = facet;
8252 else
8253 last->next = facet;
8254 last = facet;
8255 }
8256 }
8257 }
8258 }
8259 }
8260 /*
8261 * Check constraints.
8262 */
8263 xmlSchemaCheckSRCSimpleType(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008264 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008265 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008266 case XML_SCHEMA_TYPE_SEQUENCE:
8267 case XML_SCHEMA_TYPE_GROUP:
8268 case XML_SCHEMA_TYPE_ALL:
8269 case XML_SCHEMA_TYPE_CHOICE:
8270 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
8271 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008272 case XML_SCHEMA_TYPE_LIST:
Daniel Veillard3646d642004-06-02 19:19:14 +00008273 xmlSchemaParseListRefFixup(typeDecl, ctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008274 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
8275 break;
8276 case XML_SCHEMA_TYPE_UNION:
8277 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
8278 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
8279 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008280 case XML_SCHEMA_TYPE_BASIC:
8281 case XML_SCHEMA_TYPE_ANY:
8282 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008283 case XML_SCHEMA_TYPE_UR:
8284 case XML_SCHEMA_TYPE_ELEMENT:
8285 case XML_SCHEMA_TYPE_ATTRIBUTE:
8286 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +00008287 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008288 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008289 case XML_SCHEMA_FACET_MININCLUSIVE:
8290 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8291 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8292 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8293 case XML_SCHEMA_FACET_TOTALDIGITS:
8294 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8295 case XML_SCHEMA_FACET_PATTERN:
8296 case XML_SCHEMA_FACET_ENUMERATION:
8297 case XML_SCHEMA_FACET_WHITESPACE:
8298 case XML_SCHEMA_FACET_LENGTH:
8299 case XML_SCHEMA_FACET_MAXLENGTH:
8300 case XML_SCHEMA_FACET_MINLENGTH:
8301 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008302 if (typeDecl->subtypes != NULL)
8303 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008304 break;
8305 }
8306 }
Daniel Veillard8651f532002-04-17 09:06:27 +00008307#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008308 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008309 xmlGenericError(xmlGenericErrorContext,
8310 "Type of %s : %s:%d :", name,
8311 typeDecl->node->doc->URL,
8312 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008313 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008314 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008315 }
Daniel Veillard8651f532002-04-17 09:06:27 +00008316 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008317 case XML_SCHEMA_CONTENT_SIMPLE:
8318 xmlGenericError(xmlGenericErrorContext, "simple\n");
8319 break;
8320 case XML_SCHEMA_CONTENT_ELEMENTS:
8321 xmlGenericError(xmlGenericErrorContext, "elements\n");
8322 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00008323 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008324 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
8325 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00008326 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008327 xmlGenericError(xmlGenericErrorContext, "empty\n");
8328 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00008329 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008330 xmlGenericError(xmlGenericErrorContext, "mixed\n");
8331 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008332 /* Removed, since not used. */
8333 /*
Daniel Veillard8651f532002-04-17 09:06:27 +00008334 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008335 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
8336 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008337 */
Daniel Veillard8651f532002-04-17 09:06:27 +00008338 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008339 xmlGenericError(xmlGenericErrorContext, "basic\n");
8340 break;
8341 default:
8342 xmlGenericError(xmlGenericErrorContext,
8343 "not registered !!!\n");
8344 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00008345 }
8346#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00008347}
8348
8349/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008350 * xmlSchemaCheckFacet:
8351 * @facet: the facet
8352 * @typeDecl: the schema type definition
8353 * @ctxt: the schema parser context or NULL
8354 * @name: name of the type
8355 *
8356 * Checks the default values types, especially for facets
8357 *
8358 * Returns 0 if okay or -1 in cae of error
8359 */
8360int
8361xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008362 xmlSchemaTypePtr typeDecl,
8363 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008364{
8365 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
8366 int ret = 0;
8367
8368 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008369 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +00008370 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008371 }
8372 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008373 case XML_SCHEMA_FACET_MININCLUSIVE:
8374 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8375 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008376 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8377 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008378 /*
8379 * Okay we need to validate the value
8380 * at that point.
8381 */
8382 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008383 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008384
8385 /* 4.3.5.5 Constraints on enumeration Schema Components
8386 * Schema Component Constraint: enumeration valid restriction
8387 * It is an ·error· if any member of {value} is not in the
8388 * ·value space· of {base type definition}.
8389 *
8390 * minInclusive, maxInclusive, minExclusive, maxExclusive:
8391 * The value ·must· be in the
8392 * ·value space· of the ·base type·.
8393 */
8394 /*
8395 * This function is intended to deliver a compiled value
8396 * on the facet. In XML Schemas the type holding a facet,
8397 * cannot be a built-in type. Thus to ensure that other API
8398 * calls (relaxng) do work, if the given type is a built-in
8399 * type, we will assume that the given built-in type *is
8400 * already* the base type.
8401 */
8402 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
8403 base = typeDecl->baseType;
8404 if (base == NULL) {
8405 xmlSchemaPErr(ctxt, typeDecl->node,
8406 XML_SCHEMAS_ERR_INTERNAL,
8407 "Internal error: xmlSchemaCheckFacet, "
8408 "the type \"%s\" has no base type.\n",
8409 typeDecl->name, NULL);
8410 return (-1);
8411 }
8412 } else
8413 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008414 /*
8415 * TODO: Try to avoid creating a new context.
8416 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008417 vctxt = xmlSchemaNewValidCtxt(NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008418 if (vctxt == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008419 xmlSchemaPErr(ctxt, typeDecl->node,
8420 XML_SCHEMAS_ERR_INTERNAL,
8421 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008422 "creating a new validation context.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00008423 typeDecl->name, NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008424 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008425 }
8426 vctxt->type = base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008427 ret = xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1);
8428 facet->val = vctxt->value;
8429 vctxt->value = NULL;
8430 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008431 /* error code */
8432 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008433 xmlSchemaPErrExt(ctxt, facet->node,
8434 XML_SCHEMAP_INVALID_FACET,
8435 NULL, NULL, NULL,
8436 "Type \"%s\": the value \"%s\" of the "
8437 "facet \"%s\" is invalid.\n",
8438 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008439 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +00008440 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008441 }
8442 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008443 } else if (ret < 0) {
8444 xmlSchemaPErrExt(ctxt, facet->node,
8445 XML_SCHEMAS_ERR_INTERNAL,
8446 NULL, NULL, NULL,
8447 "Internal error: xmlSchemaCheckFacet, "
8448 "failed to validate the value \"%s\" name of the "
8449 "facet \"%s\" against the base type \"%s\".\n",
8450 facet->value,
8451 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
8452 base->name, NULL, NULL);
8453 ret = -1;
8454 }
8455 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008456 break;
8457 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008458 /*
8459 * Removed, since added to the case above.
8460 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008461 case XML_SCHEMA_FACET_ENUMERATION:{
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008462 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008463 * Okay we need to validate the value
8464 * at that point.
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008465 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008466 xmlSchemaValidCtxtPtr vctxt;
8467 int tmp;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008468 xmlSchemaTypePtr base;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008469
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008470 * 4.3.5.5 Constraints on enumeration Schema Components
Daniel Veillard01fa6152004-06-29 17:04:39 +00008471 * Schema Component Constraint: enumeration valid restriction
8472 * It is an ·error· if any member of {value} is not in the
8473 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008474 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008475 vctxt = xmlSchemaNewValidCtxt(NULL);
8476 if (vctxt == NULL)
8477 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008478 base = typeDecl->baseType;
8479 if (base == NULL) {
8480 xmlSchemaPErr(ctxt, typeDecl->node,
8481 XML_SCHEMAS_ERR_INTERNAL,
8482 "Internal error: xmlSchemaCheckFacet, "
8483 "the type \"%s\" has no base type.\n",
8484 typeDecl->name, NULL);
8485 return (-1);
8486 }
8487 vctxt->type = base;
8488 tmp = xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1);
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008489 * tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008490 facet->value);
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008491 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008492 if (tmp != 0) {
8493 if (ctxt != NULL) {
8494 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008495 XML_SCHEMAP_INVALID_ENUM,
8496 "Type \"%s\": the value \"%s\" of the "
8497 "facet \"enumeration\" is invalid.\n",
8498 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008499 }
8500 ret = -1;
8501 }
8502 xmlSchemaFreeValidCtxt(vctxt);
8503 break;
8504 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +00008505 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008506 case XML_SCHEMA_FACET_PATTERN:
8507 facet->regexp = xmlRegexpCompile(facet->value);
8508 if (facet->regexp == NULL) {
8509 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008510 XML_SCHEMAP_REGEXP_INVALID,
8511 "Type \"%s\": the value \"%s\" of the "
8512 "facet \"pattern\" is invalid.\n",
8513 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008514 ret = -1;
8515 }
8516 break;
8517 case XML_SCHEMA_FACET_TOTALDIGITS:
8518 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8519 case XML_SCHEMA_FACET_LENGTH:
8520 case XML_SCHEMA_FACET_MAXLENGTH:
8521 case XML_SCHEMA_FACET_MINLENGTH:{
8522 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008523
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008524 tmp =
8525 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
8526 facet->value,
8527 &facet->val);
8528 if (tmp != 0) {
8529 /* error code */
8530 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008531 xmlSchemaPErrExt(ctxt, facet->node,
8532 XML_SCHEMAP_INVALID_FACET_VALUE,
8533 NULL, NULL, NULL,
8534 "Type \"%s\": the value \"%s\" of the "
8535 "facet \"%s\" is invalid.\n",
8536 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008537 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +00008538 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008539 }
8540 ret = -1;
8541 }
8542 break;
8543 }
8544 case XML_SCHEMA_FACET_WHITESPACE:{
8545 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
8546 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
8547 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
8548 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
8549 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
8550 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
8551 } else {
8552 if (ctxt != NULL) {
8553 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008554 XML_SCHEMAP_INVALID_WHITE_SPACE,
8555 "Type \"%s\": the value \"%s\" of the "
8556 "facet \"whiteSpace\" is invalid.\n",
8557 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008558 }
8559 ret = -1;
8560 }
8561 }
8562 default:
8563 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008564 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008565 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008566}
8567
8568/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008569 * xmlSchemaCheckDefaults:
8570 * @typeDecl: the schema type definition
8571 * @ctxt: the schema parser context
8572 *
8573 * Checks the default values types, especially for facets
8574 */
8575static void
8576xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008577 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00008578{
Daniel Veillard4255d502002-04-16 15:50:10 +00008579 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +00008580 name = typeDecl->name;
8581 /*
8582 * NOTE: It is intended to use the facets list, instead
8583 * of facetSet.
8584 */
8585 if (typeDecl->facets != NULL) {
8586 xmlSchemaFacetPtr facet = typeDecl->facets;
8587
8588 while (facet != NULL) {
8589 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
8590 facet = facet->next;
8591 }
8592 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008593}
8594
8595/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00008596 * xmlSchemaAttrGrpFixup:
8597 * @attrgrpDecl: the schema attribute definition
8598 * @ctxt: the schema parser context
8599 * @name: the attribute name
8600 *
8601 * Fixes finish doing the computations on the attributes definitions
8602 */
8603static void
Daniel Veillard3646d642004-06-02 19:19:14 +00008604xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008605 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00008606{
8607 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00008608 name = attrgrp->name;
8609 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008610 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00008611 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008612 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00008613
Daniel Veillard3646d642004-06-02 19:19:14 +00008614 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref, attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008615 if (ref == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008616 xmlSchemaPErr(ctxt, attrgrp->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008617 XML_SCHEMAP_SRC_RESOLVE,
8618 "Attribute group \"%s\": the QName \"%s\" of the attribute "
8619 "\"ref\" does not resolve to a schema "
8620 "component.\n",
8621 name, attrgrp->ref);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008622 return;
8623 }
8624 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00008625 attrgrp->attributes = ref->attributes;
8626 attrgrp->attributeWildcard = ref->attributeWildcard;
8627 }
8628 /*
8629 * Removed, since a global attribute group does not need to hold any
8630 * attributes or wildcard
8631 */
8632 /*
8633 else {
8634 xmlSchemaPErr(ctxt, attrgrp->node, XML_SCHEMAP_NOATTR_NOREF,
8635 "Schemas: attribute group %s has no attributes nor reference\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008636 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00008637 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008638 */
Daniel Veillard13e04c62002-04-23 17:51:29 +00008639}
8640
8641/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008642 * xmlSchemaAttrFixup:
8643 * @attrDecl: the schema attribute definition
8644 * @ctxt: the schema parser context
8645 * @name: the attribute name
8646 *
8647 * Fixes finish doing the computations on the attributes definitions
8648 */
8649static void
8650xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008651 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00008652{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008653 /*
8654 * The simple type definition corresponding to the <simpleType> element
8655 * information item in the [children], if present, otherwise the simple
8656 * type definition ·resolved· to by the ·actual value· of the type
8657 * [attribute], if present, otherwise the ·simple ur-type definition·.
8658 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008659 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008660 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008661 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008662 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008663 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008664 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008665
Daniel Veillard01fa6152004-06-29 17:04:39 +00008666 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
8667 attrDecl->typeNs);
8668 if (type == NULL) {
8669 xmlSchemaPErr(ctxt, attrDecl->node,
8670 XML_SCHEMAP_SRC_RESOLVE,
8671 "Attribute \"%s\": the QName \"%s\" of the attribute "
8672 "\"type\" does not resolve to a schema "
8673 "component.\n",
8674 name, attrDecl->typeName);
8675 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008676 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008677 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008678 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00008679
Daniel Veillard3646d642004-06-02 19:19:14 +00008680 ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008681 if (ref == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008682 xmlSchemaPErr(ctxt, attrDecl->node,
8683 XML_SCHEMAP_SRC_RESOLVE,
8684 "Attribute \"%s\": the QName \"%s\" of the attribute "
8685 "\"ref\" does not resolve to a schema "
8686 "component.\n",
8687 name, attrDecl->ref);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008688 return;
8689 }
8690 xmlSchemaAttrFixup(ref, ctxt, NULL);
8691 attrDecl->subtypes = ref->subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +00008692 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008693 attrDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
Daniel Veillard4255d502002-04-16 15:50:10 +00008694 }
8695}
8696
8697/**
8698 * xmlSchemaParse:
8699 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00008700 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00008701 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00008702 * XML Shema struture which can be used to validate instances.
8703 * *WARNING* this interface is highly subject to change
8704 *
8705 * Returns the internal XML Schema structure built from the resource or
8706 * NULL in case of error
8707 */
8708xmlSchemaPtr
8709xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
8710{
8711 xmlSchemaPtr ret = NULL;
8712 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008713 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008714 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008715 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008716
8717 xmlSchemaInitTypes();
8718
Daniel Veillard6045c902002-10-09 21:13:59 +00008719 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00008720 return (NULL);
8721
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008722 nberrors = ctxt->nberrors;
8723 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008724 ctxt->counter = 0;
8725 ctxt->container = NULL;
8726
8727 /*
8728 * First step is to parse the input document into an DOM/Infoset
8729 */
Daniel Veillard6045c902002-10-09 21:13:59 +00008730 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008731 doc = xmlReadFile((const char *) ctxt->URL, NULL,
8732 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008733 if (doc == NULL) {
8734 xmlSchemaPErr(ctxt, NULL,
8735 XML_SCHEMAP_FAILED_LOAD,
8736 "xmlSchemaParse: could not load %s\n",
8737 ctxt->URL, NULL);
8738 return (NULL);
8739 }
Daniel Veillard6045c902002-10-09 21:13:59 +00008740 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008741 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
8742 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008743 if (doc == NULL) {
8744 xmlSchemaPErr(ctxt, NULL,
8745 XML_SCHEMAP_FAILED_PARSE,
8746 "xmlSchemaParse: could not parse\n",
8747 NULL, NULL);
8748 return (NULL);
8749 }
8750 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00008751 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00008752 } else if (ctxt->doc != NULL) {
8753 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008754 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00008755 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008756 xmlSchemaPErr(ctxt, NULL,
8757 XML_SCHEMAP_NOTHING_TO_PARSE,
8758 "xmlSchemaParse: could not parse\n",
8759 NULL, NULL);
8760 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008761 }
8762
8763 /*
8764 * Then extract the root and Schema parse it
8765 */
8766 root = xmlDocGetRootElement(doc);
8767 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008768 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8769 XML_SCHEMAP_NOROOT,
8770 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00008771 if (!preserve) {
8772 xmlFreeDoc(doc);
8773 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008774 return (NULL);
8775 }
8776
8777 /*
8778 * Remove all the blank text nodes
8779 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008780 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00008781
8782 /*
8783 * Then do the parsing for good
8784 */
8785 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00008786 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00008787 if (!preserve) {
8788 xmlFreeDoc(doc);
8789 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008790 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00008791 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008792 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008793 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00008794
8795 /*
8796 * Then fix all the references.
8797 */
8798 ctxt->schema = ret;
8799 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008800 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008801
8802 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00008803 * Then fixup all attributes declarations
8804 */
8805 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
8806
8807 /*
8808 * Then fixup all attributes group declarations
8809 */
8810 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
8811 ctxt);
8812
8813 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00008814 * Then fixup all types properties
8815 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008816 ctxt->ctxtType = NULL;
8817 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008818 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
8819
8820 /*
8821 * Then build the content model for all elements
8822 */
8823 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008824 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008825
8826 /*
8827 * Then check the defaults part of the type like facets values
8828 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008829 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
8830 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008831
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008832 if (ctxt->nberrors != 0) {
8833 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008834 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008835 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008836 return (ret);
8837}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008838
Daniel Veillard4255d502002-04-16 15:50:10 +00008839/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00008840 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00008841 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00008842 * @err: the error callback
8843 * @warn: the warning callback
8844 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00008845 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00008846 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00008847 */
8848void
8849xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008850 xmlSchemaValidityErrorFunc err,
8851 xmlSchemaValidityWarningFunc warn, void *ctx)
8852{
Daniel Veillard4255d502002-04-16 15:50:10 +00008853 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008854 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008855 ctxt->error = err;
8856 ctxt->warning = warn;
8857 ctxt->userData = ctx;
8858}
8859
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008860/**
8861 * xmlSchemaFacetTypeToString:
8862 * @type: the facet type
8863 *
8864 * Convert the xmlSchemaTypeType to a char string.
8865 *
8866 * Returns the char string representation of the facet type if the
8867 * type is a facet and an "Internal Error" string otherwise.
8868 */
8869static const char *
8870xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
8871{
8872 switch (type) {
8873 case XML_SCHEMA_FACET_PATTERN:
8874 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008875 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008876 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008877 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008878 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008879 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008880 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008881 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008882 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008883 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008884 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008885 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008886 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008887 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008888 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008889 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008890 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008891 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008892 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008893 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008894 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008895 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008896 return ("fractionDigits");
8897 default:
8898 break;
8899 }
8900 return ("Internal Error");
8901}
8902
8903/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00008904 * xmlSchemaValidateFacetsInternal:
8905 * @ctxt: a schema validation context
8906 * @base: the base type
8907 * @facets: the list of facets to check
8908 * @value: the lexical repr of the value to validate
8909 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +00008910 * @fireErrors: if 0, only internal errors will be fired;
8911 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00008912 *
8913 * Check a value against all facet conditions
8914 *
8915 * Returns 0 if the element is schemas valid, a positive error code
8916 * number otherwise and -1 in case of internal or API error.
8917 */
8918static int
8919xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
8920 xmlSchemaTypePtr base,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008921 xmlSchemaFacetLinkPtr facets,
William M. Bracke7091952004-05-11 15:09:58 +00008922 const xmlChar * value, int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00008923{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008924 int ret = 0;
8925 int tmp = 0;
8926 xmlSchemaTypeType type;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008927 xmlSchemaFacetLinkPtr facetLink = facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008928
Daniel Veillard01fa6152004-06-29 17:04:39 +00008929 while (facetLink != NULL) {
8930 type = facetLink->facet->type;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008931 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008932 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008933
Daniel Veillard01fa6152004-06-29 17:04:39 +00008934 while (facetLink != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008935 tmp =
Daniel Veillard01fa6152004-06-29 17:04:39 +00008936 xmlSchemaValidateFacet(base, facetLink->facet, value,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008937 ctxt->value);
8938 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008939 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008940 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008941 facetLink = facetLink->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008942 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008943 } else
Daniel Veillard01fa6152004-06-29 17:04:39 +00008944 tmp = xmlSchemaValidateFacet(base, facetLink->facet, value,
8945 ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008946
8947 if (tmp != 0) {
8948 ret = tmp;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008949 if (fireErrors) {
8950 xmlSchemaVErr(ctxt, ctxt->cur, tmp,
8951 "The value failed to validate against the facet \"%s\".\n",
8952 (const xmlChar *) xmlSchemaFacetTypeToString(type),
8953 NULL);
8954
8955 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008956 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008957 if (facetLink != NULL)
8958 facetLink = facetLink->next;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00008959 }
8960 return (ret);
8961}
8962
Daniel Veillard4255d502002-04-16 15:50:10 +00008963/************************************************************************
8964 * *
8965 * Simple type validation *
8966 * *
8967 ************************************************************************/
Daniel Veillard01fa6152004-06-29 17:04:39 +00008968#if 0 /* Not currently used. */
Daniel Veillard4255d502002-04-16 15:50:10 +00008969/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00008970 * xmlSchemaValidateSimpleValueUnion:
8971 * @ctxt: a schema validation context
8972 * @type: the type declaration
8973 * @value: the value to validate
8974 *
8975 * Validates a value against a union.
8976 *
8977 * Returns 0 if the value is valid, a positive error code
8978 * number otherwise and -1 in case of internal or API error.
8979 */
8980static int
8981xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
8982 xmlSchemaTypePtr type, const xmlChar * value)
8983{
8984 int ret = 0;
8985 const xmlChar *cur, *end, *prefix, *ncName;
8986 xmlChar *tmp;
8987 xmlSchemaTypePtr subtype;
8988 xmlNsPtr ns;
8989 int len;
8990
8991
8992 /* Process referenced memberTypes. */
8993 cur = type->ref;
8994 do {
8995 while (IS_BLANK_CH(*cur))
8996 cur++;
8997 end = cur;
8998 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8999 end++;
9000 if (end == cur)
9001 break;
9002 tmp = xmlStrndup(cur, end - cur);
9003 ncName = xmlSplitQName3(tmp, &len);
9004 if (ncName != NULL) {
9005 prefix = xmlStrndup(tmp, len);
9006 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
9007 } else {
9008 prefix = NULL;
9009 ncName = tmp;
9010 }
William M. Bracke7091952004-05-11 15:09:58 +00009011 /* We won't do additional checks here,
9012 * since they have been performed during parsing. */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009013 ns = xmlSearchNs(type->node->doc, type->node, prefix);
9014 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
9015 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
9016 if (tmp != NULL)
9017 xmlFree(tmp);
9018 if (prefix != NULL)
William M. Brack87640d52004-04-17 14:58:15 +00009019 xmlFree((void *)prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009020 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
9021 if ((ret == 0) || (ret == -1)) {
9022 return (ret);
9023 }
9024 cur = end;
9025 } while (*cur != 0);
9026
9027 if (type->subtypes != NULL) {
9028 subtype = type->subtypes;
9029 do {
9030 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
9031 if ((ret == 0) || (ret == -1)) {
9032 return (ret);
9033 }
9034 subtype = subtype->next;
9035 } while (subtype != NULL);
9036 }
9037 return (ret);
9038}
9039
9040/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009041 * xmlSchemaValidateSimpleValue:
9042 * @ctxt: a schema validation context
9043 * @type: the type declaration
9044 * @value: the value to validate
9045 *
9046 * Validate a value against a simple type
9047 *
9048 * Returns 0 if the value is valid, a positive error code
9049 * number otherwise and -1 in case of internal or API error.
9050 */
9051static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009052xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009053 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009054{
Daniel Veillard377e1a92004-04-16 16:30:05 +00009055 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
9056}
9057
9058/**
9059 * xmlSchemaValidateSimpleValue:
9060 * @ctxt: a schema validation context
9061 * @type: the type declaration
9062 * @value: the value to validate
William M. Bracke7091952004-05-11 15:09:58 +00009063 * @fireErrors: if 0, only internal errors will be fired;
9064 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00009065 *
9066 * Validate a value against a simple type
9067 *
9068 * Returns 0 if the value is valid, a positive error code
9069 * number otherwise and -1 in case of internal or API error.
9070 */
9071static int
9072xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
William M. Bracke7091952004-05-11 15:09:58 +00009073 xmlSchemaTypePtr type,
9074 const xmlChar * value,
9075 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00009076{
Daniel Veillard4255d502002-04-16 15:50:10 +00009077 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009078
Daniel Veillard4255d502002-04-16 15:50:10 +00009079 /*
9080 * First normalize the value accordingly to Schema Datatype
9081 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
William M. Bracke7091952004-05-11 15:09:58 +00009082 *
Daniel Veillard4255d502002-04-16 15:50:10 +00009083 * Then check the normalized value against the lexical space of the
9084 * type.
9085 */
9086 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009087 if (ctxt->value != NULL) {
9088 xmlSchemaFreeValue(ctxt->value);
9089 ctxt->value = NULL;
9090 }
9091 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
9092 ctxt->cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009093 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00009094 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
9095 "Failed to validate basic type %s\n",
9096 type->name, NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009097 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009098 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009099 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00009100
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009101 base = type->baseType;
9102 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00009103 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
9104 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009105 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009106 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009107 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009108
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009109 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00009110 * Do not validate facets or attributes when working on
9111 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009112 */
9113 if (ctxt->schema != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009114 xmlSchemaFacetLinkPtr facetLink;
9115
9116 if ((ret == 0) && (type->facetSet != NULL)) {
9117 facetLink = type->facetSet;
9118 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facetLink,
William M. Bracke7091952004-05-11 15:09:58 +00009119 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009120 }
9121 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009122 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009123 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00009124
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009125 base = type->subtypes;
9126 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00009127 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
9128 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009129 } else {
9130 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00009131 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009132 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009133 const xmlChar *cur, *end;
9134 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009135 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00009136
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009137 base = type->subtypes;
9138 if (base == NULL) {
9139 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
9140 "Internal: List type %s has no base type\n",
9141 type->name, NULL);
9142 return (-1);
9143 }
9144 cur = value;
9145 do {
William M. Brack76e95df2003-10-18 16:20:14 +00009146 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009147 cur++;
9148 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00009149 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009150 end++;
9151 if (end == cur)
9152 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009153 tmp = xmlStrndup(cur, end - cur);
William M. Bracke7091952004-05-11 15:09:58 +00009154 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base,
9155 tmp, fireErrors);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009156 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009157 if (ret2 != 0)
9158 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009159 cur = end;
9160 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009161 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
9162 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
9163 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00009164 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
9165 "Failed to validate type %s\n", type->name, NULL);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009166 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009167 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009168 TODO
9169 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009170 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009171}
Daniel Veillard01fa6152004-06-29 17:04:39 +00009172#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009173
9174/************************************************************************
9175 * *
9176 * DOM Validation code *
9177 * *
9178 ************************************************************************/
9179
9180static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009181 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009182static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009183 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +00009184 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00009185static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009186 xmlNodePtr elem,
9187 xmlSchemaElementPtr elemDecl,
9188 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00009189
Daniel Veillard3646d642004-06-02 19:19:14 +00009190
9191/**
9192 * xmlSchemaFreeAttrStates:
9193 * @state: a list of attribute states
9194 *
9195 * Free the given list of attribute states
9196 *
9197 */
9198static void
9199xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
9200{
9201 xmlSchemaAttrStatePtr tmp;
9202 while (state != NULL) {
9203 tmp = state;
9204 state = state->next;
9205 xmlFree(tmp);
9206 }
9207}
9208
Daniel Veillard4255d502002-04-16 15:50:10 +00009209/**
9210 * xmlSchemaRegisterAttributes:
9211 * @ctxt: a schema validation context
9212 * @attrs: a list of attributes
9213 *
9214 * Register the list of attributes as the set to be validated on that element
9215 *
9216 * Returns -1 in case of error, 0 otherwise
9217 */
9218static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009219xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
9220{
Daniel Veillard3646d642004-06-02 19:19:14 +00009221 xmlSchemaAttrStatePtr tmp;
9222
9223 ctxt->attr = NULL;
9224 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009225 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009226 if ((attrs->ns != NULL) &&
9227 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
9228 attrs = attrs->next;
9229 continue;
9230 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009231 tmp = (xmlSchemaAttrStatePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00009232 xmlMalloc(sizeof(xmlSchemaAttrState));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009233 if (tmp == NULL) {
9234 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009235 return (-1);
9236 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009237 tmp->attr = attrs;
9238 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
9239 tmp->next = NULL;
9240 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009241 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009242 else
9243 ctxt->attrTop->next = tmp;
9244 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009245 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009246 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009247 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00009248}
9249
9250/**
9251 * xmlSchemaCheckAttributes:
9252 * @ctxt: a schema validation context
9253 * @node: the node carrying it.
9254 *
9255 * Check that the registered set of attributes on the current node
9256 * has been properly validated.
9257 *
9258 * Returns 0 if validity constraints are met, 1 otherwise.
9259 */
9260static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009261xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
9262{
Daniel Veillard4255d502002-04-16 15:50:10 +00009263 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009264 xmlSchemaAttrStatePtr cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00009265
Daniel Veillard3646d642004-06-02 19:19:14 +00009266 cur = ctxt->attr;
9267 while ((cur != NULL) && (cur != ctxt->attrTop->next)) {
9268 if (cur->state != XML_SCHEMAS_ATTR_CHECKED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009269 ret = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00009270 if (cur->state == XML_SCHEMAS_ATTR_UNKNOWN)
William M. Bracke7091952004-05-11 15:09:58 +00009271 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009272 "Attribute \"%s\" is not allowed.\n",
9273 cur->attr->name, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009274 else if (cur->state == XML_SCHEMAS_ATTR_PROHIBITED)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009275 /*
9276 * TODO: This won't ever be touched so remove it.
9277 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009278 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009279 "Attribute \"%s\" is prohibited.\n",
9280 cur->attr->name, NULL);
9281 else if (cur->state == XML_SCHEMAS_ATTR_INVALID_VALUE) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009282 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRINVALID,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009283 "Attribute \"%s\": the value is not valid.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009284 cur->attr->name, node->name);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009285 } else if (cur->state == XML_SCHEMAS_ATTR_MISSING) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009286 if (cur->decl->ref != NULL)
9287 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009288 "Attribute \"%s\" is required but missing.\n",
9289 cur->decl->ref, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009290 else
9291 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009292 "Attribute \"%s\" is required but missing.\n",
9293 cur->decl->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009294 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009295 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009296 cur = cur->next;
9297 }
9298
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009299 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009300}
9301
William M. Brack29aa7722004-05-12 00:27:56 +00009302#if 0 /* Not currently used - remove if ever needed */
Daniel Veillard4255d502002-04-16 15:50:10 +00009303/**
9304 * xmlSchemaValidateSimpleContent:
9305 * @ctxt: a schema validation context
9306 * @elem: an element
9307 * @type: the type declaration
9308 *
9309 * Validate the content of an element expected to be a simple type
9310 *
9311 * Returns 0 if the element is schemas valid, a positive error code
9312 * number otherwise and -1 in case of internal or API error.
9313 */
9314static int
9315xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009316 xmlNodePtr node ATTRIBUTE_UNUSED)
9317{
Daniel Veillard4255d502002-04-16 15:50:10 +00009318 xmlNodePtr child;
9319 xmlSchemaTypePtr type, base;
9320 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009321 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009322
9323 child = ctxt->node;
9324 type = ctxt->type;
9325
9326 /*
9327 * Validation Rule: Element Locally Valid (Type): 3.1.3
9328 */
9329 value = xmlNodeGetContent(child);
9330 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
9331 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009332 case XML_SCHEMA_TYPE_RESTRICTION:{
9333 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00009334
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009335 base = type->baseType;
9336 if (base != NULL) {
9337 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
9338 } else {
9339 TODO}
9340 if (ret == 0) {
9341 facet = type->facets;
9342 ret =
9343 xmlSchemaValidateFacets(ctxt, base, facet, value);
9344 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009345 /*
9346 * This should attempt to validate the attributes even
9347 * when validation of the value failed.
9348 */
9349 /*
9350 if (type->attributes != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00009351 ret = xmlSchemaValidateAttributes(ctxt, node,
9352 type->attributes);
9353 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009354 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009355 break;
9356 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009357 case XML_SCHEMA_TYPE_EXTENSION:{
9358 TODO
9359 break;
9360 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009361 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009362 TODO
9363 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009364 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009365 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00009366
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009367 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009368}
William M. Brack29aa7722004-05-12 00:27:56 +00009369#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009370
9371/**
9372 * xmlSchemaValidateCheckNodeList
9373 * @nodelist: the list of nodes
9374 *
9375 * Check the node list is only made of text nodes and entities pointing
9376 * to text nodes
9377 *
9378 * Returns 1 if true, 0 if false and -1 in case of error
9379 */
9380static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009381xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
9382{
Daniel Veillard4255d502002-04-16 15:50:10 +00009383 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009384 if (nodelist->type == XML_ENTITY_REF_NODE) {
9385 TODO /* implement recursion in the entity content */
9386 }
9387 if ((nodelist->type != XML_TEXT_NODE) &&
9388 (nodelist->type != XML_COMMENT_NODE) &&
9389 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +00009390 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009391 return (0);
9392 }
9393 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009394 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009395 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009396}
9397
9398/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009399 * xmlSchemaValidateCallback:
9400 * @ctxt: a schema validation context
9401 * @name: the name of the element detected (might be NULL)
9402 * @type: the type
9403 *
9404 * A transition has been made in the automata associated to an element
9405 * content model
9406 */
9407static void
9408xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009409 const xmlChar * name ATTRIBUTE_UNUSED,
9410 xmlSchemaTypePtr type, xmlNodePtr node)
9411{
Daniel Veillard4255d502002-04-16 15:50:10 +00009412 xmlSchemaTypePtr oldtype = ctxt->type;
9413 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009414
Daniel Veillard4255d502002-04-16 15:50:10 +00009415#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00009416 xmlGenericError(xmlGenericErrorContext,
9417 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009418 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00009419#endif
9420 ctxt->type = type;
9421 ctxt->node = node;
9422 xmlSchemaValidateContent(ctxt, node);
9423 ctxt->type = oldtype;
9424 ctxt->node = oldnode;
9425}
9426
9427
9428#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009429
Daniel Veillard4255d502002-04-16 15:50:10 +00009430/**
9431 * xmlSchemaValidateSimpleRestrictionType:
9432 * @ctxt: a schema validation context
9433 * @node: the top node.
9434 *
9435 * Validate the content of a restriction type.
9436 *
9437 * Returns 0 if the element is schemas valid, a positive error code
9438 * number otherwise and -1 in case of internal or API error.
9439 */
9440static int
9441xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
9442 xmlNodePtr node)
9443{
9444 xmlNodePtr child;
9445 xmlSchemaTypePtr type;
9446 int ret;
9447
9448 child = ctxt->node;
9449 type = ctxt->type;
9450
9451 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00009452 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9453 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
9454 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009455 return (-1);
9456 }
9457 /*
9458 * Only text and text based entities references shall be found there
9459 */
9460 ret = xmlSchemaValidateCheckNodeList(child);
9461 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00009462 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009463 "Internal error: xmlSchemaValidateSimpleRestrictionType %s content\n",
William M. Bracke7091952004-05-11 15:09:58 +00009464 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009465 return (-1);
9466 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00009467 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
9468 "Element %s content is not a simple type\n",
9469 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009470 return (-1);
9471 }
9472 ctxt->type = type->subtypes;
9473 xmlSchemaValidateContent(ctxt, node);
9474 ctxt->type = type;
9475 return (ret);
9476}
9477#endif
9478
Daniel Veillard01fa6152004-06-29 17:04:39 +00009479#if 0 /* Not used any more */
Daniel Veillard4255d502002-04-16 15:50:10 +00009480/**
9481 * xmlSchemaValidateSimpleType:
9482 * @ctxt: a schema validation context
9483 * @node: the top node.
9484 *
9485 * Validate the content of an simple type.
9486 *
9487 * Returns 0 if the element is schemas valid, a positive error code
9488 * number otherwise and -1 in case of internal or API error.
9489 */
9490static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009491xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
9492{
Daniel Veillard4255d502002-04-16 15:50:10 +00009493 xmlNodePtr child;
William M. Bracke7091952004-05-11 15:09:58 +00009494 xmlSchemaTypePtr type, base, variety;
Daniel Veillard4255d502002-04-16 15:50:10 +00009495 xmlAttrPtr attr;
9496 int ret;
William M. Bracke7091952004-05-11 15:09:58 +00009497 xmlChar *value;
9498
Daniel Veillard4255d502002-04-16 15:50:10 +00009499
9500 child = ctxt->node;
9501 type = ctxt->type;
9502
9503 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00009504 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9505 "Internal error: xmlSchemaValidateSimpleType %s\n",
9506 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009507 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009508 }
9509 /*
9510 * Only text and text based entities references shall be found there
9511 */
9512 ret = xmlSchemaValidateCheckNodeList(child);
9513 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00009514 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9515 "Internal error: xmlSchemaValidateSimpleType %s content\n",
9516 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009517 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009518 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00009519 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
9520 "Element %s content is not a simple type\n",
9521 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009522 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009523 }
9524 /*
9525 * Validation Rule: Element Locally Valid (Type): 3.1.1
William M. Bracke7091952004-05-11 15:09:58 +00009526 */
9527
Daniel Veillard4255d502002-04-16 15:50:10 +00009528 attr = node->properties;
9529 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009530 if ((attr->ns == NULL) ||
9531 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
9532 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
9533 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
9534 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
9535 (!xmlStrEqual
9536 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
William M. Bracke7091952004-05-11 15:09:58 +00009537 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
9538 "Element %s: attribute %s should not be present\n",
9539 node->name, attr->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009540 return (ctxt->err);
9541 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009542 }
William M. Bracke7091952004-05-11 15:09:58 +00009543 /* TODO:
9544 * If {variety} is ·atomic· then the {variety} of {base type definition}
9545 * must be ·atomic·.
9546 * If {variety} is ·list· then the {variety} of {item type definition}
9547 * must be either ·atomic· or ·union·.
9548 * If {variety} is ·union· then {member type definitions} must be a list
9549 * of datatype definitions.
9550 */
9551 if (type->subtypes == NULL) {
9552 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9553 "Internal error: xmlSchemaValidateSimpleType; "
9554 "simple type %s does not define a variety\n",
9555 node->name, NULL);
9556 return (ctxt->err);
9557 }
9558 /* Varieties: Restriction or List or Union. */
9559 variety = type->subtypes;
9560 ctxt->type = variety;
9561 value = xmlNodeGetContent(child);
9562 switch (variety->type) {
9563 case XML_SCHEMA_TYPE_RESTRICTION:{
William M. Bracke7091952004-05-11 15:09:58 +00009564 base = variety->baseType;
9565 if (base != NULL) {
9566 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
9567 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009568 TODO}
9569
Daniel Veillard3646d642004-06-02 19:19:14 +00009570 /* Removed due to changes of attribute validation:
William M. Bracke7091952004-05-11 15:09:58 +00009571 if ((ret == 0) && (variety->attributes != NULL)) {
9572 ret = xmlSchemaValidateAttributes(ctxt, node,
9573 variety->attributes);
9574 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009575 */
William M. Bracke7091952004-05-11 15:09:58 +00009576 break;
9577 }
9578 case XML_SCHEMA_TYPE_LIST:
9579 case XML_SCHEMA_TYPE_UNION: {
9580 ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
9581 break;
9582 }
9583 default:{
9584 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9585 "Internal error: xmlSchemaValidateSimpleType; "
9586 "simple type %s defines unknown content: %s\n",
9587 variety->name, NULL);
9588 ret = ctxt->err;
9589 }
9590 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009591 if ((ret == 0) && (variety->facetSet != NULL)) {
9592 ret = xmlSchemaValidateFacets(ctxt, base, variety->facetSet, value);
9593 }
William M. Bracke7091952004-05-11 15:09:58 +00009594 if (value != NULL)
9595 xmlFree(value);
9596
9597 /* This was removed, since a simple content is not a content of a
9598 * simple type, but of a complex type.
9599 * ret = xmlSchemaValidateSimpleContent(ctxt, node);
9600 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009601 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009602 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009603}
Daniel Veillard01fa6152004-06-29 17:04:39 +00009604#endif
9605
9606/**
9607 * xmlSchemaValidateSimpleTypeValue:
9608 * @ctxt: a schema validation context
9609 * @value: the value to be validated
9610 * @fireErrors: shall errors be reported?
9611 * @applyFacets: shall facets be applied?
9612 *
9613 * Validates a value by the given type (user derived or built-in).
9614 *
9615 * Returns 0 if the value is valid, a positive error code
9616 * number otherwise and -1 in case of an internal or API error.
9617 * Note on reported errors: Although it might be nice to report
9618 * the name of the simple/complex type, used to validate the content
9619 * of a node, it is quite unnecessary: for global defined types
9620 * the local name of the element is equal to the NCName of the type,
9621 * for local defined types it makes no sense to output the internal
9622 * computed name of the type. TODO: Instead, one should attach the
9623 * struct of the type involved to the error handler - this allows
9624 * the report of any additional information by the user.
9625 * TODO: Correct character normalization of union simple types.
9626 */
9627static int
9628xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
9629 const xmlChar *value,
9630 int fireErrors,
9631 int applyFacets)
9632{
9633 xmlSchemaTypePtr type;
9634 int ret = 0;
9635 type = ctxt->type;
9636
9637 if (type->type == XML_SCHEMA_TYPE_BASIC) {
9638 xmlNodePtr child;
9639
9640 if (ctxt->value != NULL) {
9641 xmlSchemaFreeValue(ctxt->value);
9642 ctxt->value = NULL;
9643 }
9644 child = ctxt->node;
9645 while (child != NULL) {
9646 switch (child->type) {
9647 case XML_TEXT_NODE:
9648 case XML_CDATA_SECTION_NODE:
9649 case XML_PI_NODE:
9650 case XML_COMMENT_NODE:
9651 case XML_XINCLUDE_START:
9652 case XML_XINCLUDE_END:
9653 break;
9654 case XML_ENTITY_REF_NODE:
9655 case XML_ENTITY_NODE:
9656 TODO break;
9657 case XML_ELEMENT_NODE:
9658 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INVALIDELEM,
9659 "Element \"%s\": child \"%s\" should not be present.\n",
9660 ctxt->cur->name, child->name);
9661 return (ctxt->err);
9662 case XML_ATTRIBUTE_NODE:
9663 case XML_DOCUMENT_NODE:
9664 case XML_DOCUMENT_TYPE_NODE:
9665 case XML_DOCUMENT_FRAG_NODE:
9666 case XML_NOTATION_NODE:
9667 case XML_HTML_DOCUMENT_NODE:
9668 case XML_DTD_NODE:
9669 case XML_ELEMENT_DECL:
9670 case XML_ATTRIBUTE_DECL:
9671 case XML_ENTITY_DECL:
9672 case XML_NAMESPACE_DECL:
9673#ifdef LIBXML_DOCB_ENABLED
9674 case XML_DOCB_DOCUMENT_NODE:
9675#endif
9676 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INVALIDELEM,
9677 "Element \"%s\": node type of node unexpected here.\n",
9678 ctxt->cur->name, NULL);
9679 return (ctxt->err);
9680 }
9681 child = child->next;
9682 }
9683 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
9684 ctxt->cur);
9685 if (ret > 0) {
9686 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
9687 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
9688 else
9689 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
9690 if (fireErrors) {
9691 if (ctxt->cur->type == XML_ATTRIBUTE_NODE)
9692 xmlSchemaVErr(ctxt, ctxt->cur,
9693 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
9694 "The value of attribute \"%s\" is not valid.\n",
9695 ctxt->cur->name, NULL);
9696 else
9697 xmlSchemaVErr(ctxt, ctxt->cur,
9698 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
9699 "The value is not valid.\n",
9700 NULL, NULL);
9701 }
9702 } else if (ret < 0) {
9703 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9704 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9705 "validating built-in type \"%s\"\n",
9706 type->name, NULL);
9707 }
9708 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
9709 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
9710 * a literal in the ·lexical space· of {base type definition}
9711 */
9712 ctxt->type = type->baseType;
9713 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 0);
9714 if (ret < 0) {
9715 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9716 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9717 "validating atomic simple type \"%s\"\n",
9718 type->name, NULL);
9719 } else if (ret > 0) {
9720 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
9721 if (fireErrors) {
9722 xmlSchemaVErr(ctxt, ctxt->cur,
9723 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
9724 "The value is not valid.\n",
9725 NULL, NULL);
9726 }
9727
9728 } else if ((applyFacets) &&
9729 (type->facetSet != NULL)) {
9730 xmlSchemaTypePtr builtIn;
9731
9732 /*
9733 * Check facets. Be sure to pass the built-in type to
9734 * xmlSchemaValidateFacetsInternal.
9735 */
9736 builtIn = type->baseType;
9737 while (builtIn->type != XML_SCHEMA_TYPE_BASIC)
9738 builtIn = builtIn->baseType;
9739 ret = xmlSchemaValidateFacetsInternal(ctxt, builtIn,
9740 type->facetSet, value, fireErrors);
9741 if (ret < 0) {
9742 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9743 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9744 "validating facets of atomic simple type \"%s\"\n",
9745 type->name, NULL);
9746 } else if (ret > 0) {
9747 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
9748 if (fireErrors) {
9749 xmlSchemaVErr(ctxt, ctxt->cur,
9750 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
9751 "The value is not valid.\n",
9752 NULL, NULL);
9753 }
9754 }
9755 }
9756 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
9757
9758 xmlSchemaTypePtr tmpType;
9759 const xmlChar *cur, *end;
9760 xmlChar *tmp;
9761 int len = 0;
9762
9763 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
9764 * of white space separated tokens, each of which ·match·es a literal
9765 * in the ·lexical space· of {item type definition}
9766 */
9767
9768 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
9769 cur = value;
9770 do {
9771 while (IS_BLANK_CH(*cur))
9772 cur++;
9773 end = cur;
9774 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9775 end++;
9776 if (end == cur)
9777 break;
9778 tmp = xmlStrndup(cur, end - cur);
9779 len++;
9780 ctxt->type = tmpType;
9781 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmp, 0, 1);
9782 xmlFree(tmp);
9783 if (ret > 0) {
9784 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
9785 if (fireErrors) {
9786 xmlSchemaVErr(ctxt, ctxt->cur,
9787 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
9788 "The value is not valid.\n",
9789 NULL, NULL);
9790 }
9791 break;
9792 } else if (ret < 0)
9793 break;
9794 cur = end;
9795 } while (*cur != 0);
9796 /*
9797 * Check facets.
9798 */
9799 if (ret < 0) {
9800 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9801 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9802 "validating list simple type \"%s\"\n",
9803 type->name, NULL);
9804 } else if ((ret == 0) && (applyFacets) &&
9805 (type->facetSet != NULL)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009806 int okFacet = 0, hasFacet = 0;
9807 unsigned long expLen;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009808 xmlSchemaFacetPtr facet;
9809 xmlSchemaFacetLinkPtr facetLink;
9810 xmlChar *collapsedValue = NULL;
9811
9812 /*
9813 * The value of ·whiteSpace· is fixed to the value collapse.
9814 */
9815 collapsedValue = xmlSchemaCollapseString((const xmlChar *) value);
9816 if (collapsedValue != NULL)
9817 value = (const xmlChar *) collapsedValue;
9818 facetLink = type->facetSet;
9819 do {
9820 facet = facetLink->facet;
9821 /*
9822 * List types need a special facet treatment.
9823 * Skip whiteSpace, since it is fixed to "collapse".
9824 */
9825 if ((facet->type != XML_SCHEMA_FACET_WHITESPACE) &&
9826 (facet->type != XML_SCHEMA_FACET_PATTERN)) {
9827 ret = xmlSchemaValidateListSimpleTypeFacet(facet, value,
9828 len, &expLen);
9829 if (facet->type == XML_SCHEMA_FACET_ENUMERATION) {
9830 hasFacet = 1;
9831 if (ret == 0)
9832 okFacet = 1;
9833 } else if ((ret > 0) && (fireErrors)) {
9834 char l[25], fl[25];
9835 /* FIXME: What is the max expected string length of the
9836 * length value?
9837 */
9838 snprintf(l, 24, "%d", len);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009839 snprintf(fl, 24, "%lu", expLen);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009840 if (ret == XML_SCHEMAV_CVC_LENGTH_VALID) {
9841 xmlSchemaVErr(ctxt, ctxt->cur, ret,
9842 "The value with length \"%s\" is not "
9843 "facet-valid with respect to length = \"%s\".\n",
William M. Brack96d2eff2004-06-30 11:48:47 +00009844 (const xmlChar *)l, (const xmlChar *)fl);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009845 } else if (ret == XML_SCHEMAV_CVC_MINLENGTH_VALID) {
9846 xmlSchemaVErr(ctxt, ctxt->cur, ret,
9847 "The value with length \"%s\" is not "
9848 "facet-valid with respect to minLength = \"%s\".\n",
William M. Brack96d2eff2004-06-30 11:48:47 +00009849 (const xmlChar *)l, (const xmlChar *)fl);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009850 } else if (ret == XML_SCHEMAV_CVC_MAXLENGTH_VALID) {
9851 xmlSchemaVErr(ctxt, ctxt->cur, ret,
9852 "The value with length \"%s\" is not "
9853 "facet-valid with respect to maxLength = \"%s\".\n",
William M. Brack96d2eff2004-06-30 11:48:47 +00009854 (const xmlChar *)l, (const xmlChar *)fl);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009855 } else {
9856 xmlSchemaVErr(ctxt, ctxt->cur, ret,
9857 "The value is not valid with respect "
9858 "to the facet \"%s\".\n",
William M. Brack96d2eff2004-06-30 11:48:47 +00009859 (const xmlChar *)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009860 xmlSchemaFacetTypeToString(facet->type),
9861 NULL);
9862 }
9863 } else if (ret < 0) {
9864 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9865 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9866 "validating facets of list simple type \"%s\"\n",
9867 type->name, NULL);
9868 break;
9869 }
9870 }
9871 facetLink = facetLink->next;
9872 } while (facetLink != NULL);
9873 if (ret >= 0) {
9874 if ((hasFacet) && (okFacet == 0)) {
9875 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
9876 if (fireErrors) {
9877 /*
9878 * TODO: Try to create a report that outputs all the enumeration
9879 * values in use.
9880 */
9881 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_CVC_ENUMERATION_VALID,
9882 "The value is not valid with respect "
9883 "to the \"enumeration\" facet(s).\n",
9884 NULL, NULL);
9885 }
9886
9887 }
9888 /*
9889 * Pattern facets are ORed at type level and ANDed
9890 * if derived. Walk the base axis.
9891 */
9892 hasFacet = 0;
9893 tmpType = type;
9894 do {
9895 okFacet = 0;
9896 for (facetLink = tmpType->facetSet; facetLink != NULL;
9897 facetLink = facetLink->next) {
9898 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
9899 continue;
9900 okFacet = xmlSchemaValidateListSimpleTypeFacet(
9901 facetLink->facet, value, len, &expLen);
9902 if (okFacet <= 0)
9903 break;
9904 }
9905 if (okFacet != 0)
9906 break;
9907 tmpType = tmpType->baseType;
9908 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
9909 if (okFacet < 0) {
9910 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9911 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9912 "validating \"pattern\" facets of type \"%s\"\n",
9913 type->name, NULL);
9914 } else if (okFacet > 0) {
9915 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
9916 if (fireErrors) {
9917 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_CVC_ENUMERATION_VALID,
9918 "The value is not valid with respect "
9919 "to the \"pattern\" facet(s) of type "
9920 "\"%s\".\n",
9921 tmpType->name, NULL);
9922 }
9923 }
9924 }
9925
9926 if (collapsedValue != NULL)
9927 xmlFree(collapsedValue);
9928 }
9929 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9930 xmlSchemaTypeLinkPtr memberLink;
9931
9932 /*
9933 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
9934 * not apply directly; however, the normalization behavior of ·union·
9935 * types is controlled by the value of whiteSpace on that one of the
9936 * ·memberTypes· against which the ·union· is successfully validated.
9937 *
9938 * This means that the value is normalized by the first validating
9939 * member type, then the facets of the union type are applied. This
9940 * needs changing of the value!
9941 */
9942
9943 /*
9944 * 1.2.3 if {variety} is ·union· then the string must ·match· a
9945 * literal in the ·lexical space· of at least one member of
9946 * {member type definitions}
9947 */
9948 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
9949 if (memberLink == NULL) {
9950 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9951 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9952 "union simple type \"%s\" has no member types\n",
9953 type->name, NULL);
9954 ret = -1;
9955 }
9956 if (ret == 0) {
9957 while (memberLink != NULL) {
9958 ctxt->type = memberLink->type;
9959 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1);
9960 if ((ret <= 0) || (ret == 0))
9961 break;
9962 memberLink = memberLink->next;
9963 }
9964 if (ret > 0) {
9965 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
9966 if (fireErrors) {
9967 xmlSchemaVErr(ctxt, ctxt->cur,
9968 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3,
9969 "The value is not valid.\n",
9970 NULL, NULL);
9971 }
9972 } else if (ret < 0) {
9973 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9974 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9975 "validating members of union simple type \"%s\"\n",
9976 type->name, NULL);
9977 }
9978 }
9979 /*
9980 * Apply facets (pattern, enumeration).
9981 */
9982 if ((ret == 0) && (applyFacets) &&
9983 (type->facetSet != NULL)) {
9984 xmlSchemaTypePtr anySimpleType;
9985 /*
9986 * Check facets. Be sure to pass the built-in type (the
9987 * simple ur-type in this case) to xmlSchemaValidateFacetsInternal.
9988 */
9989 anySimpleType = type->baseType;
9990 while (anySimpleType->type != XML_SCHEMA_TYPE_BASIC)
9991 anySimpleType = anySimpleType->baseType;
9992 ret = xmlSchemaValidateFacetsInternal(ctxt, anySimpleType,
9993 type->facetSet, value, fireErrors);
9994 if (ret < 0) {
9995 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9996 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9997 "validating facets of union simple type \"%s\"\n",
9998 type->name, NULL);
9999 } else if (ret > 0) {
10000 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
10001 if (fireErrors) {
10002 xmlSchemaVErr(ctxt, ctxt->cur,
10003 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
10004 "The value is not valid.\n",
10005 NULL, NULL);
10006 }
10007 }
10008 }
10009 }
10010 ctxt->type = type;
10011 return (ret);
10012}
10013
10014/**
10015 * xmlSchemaValidateSimpleTypeElement:
10016 * @ctxt: a schema validation context
10017 * @node: the element node to be validated.
10018 *
10019 * Validate the element against a simple type.
10020 *
10021 * Returns 0 if the element is valid, a positive error code
10022 * number otherwise and -1 in case of an internal or API error.
10023 */
10024static int
10025xmlSchemaValidateSimpleTypeElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10026{
10027 xmlNodePtr child;
10028 xmlSchemaTypePtr type;
10029 xmlAttrPtr attr;
10030 int ret;
10031 xmlChar *value;
10032
10033
10034 child = ctxt->node;
10035 type = ctxt->type;
10036
10037 if ((ctxt == NULL) || (type == NULL)) {
10038 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10039 "Internal error: xmlSchemaValidateSimpleTypeElement %s\n",
10040 node->name, NULL);
10041 return (-1);
10042 }
10043
10044 /*
10045 * Only text and text based entities references shall be found there
10046 */
10047 ret = xmlSchemaValidateCheckNodeList(child);
10048 if (ret < 0) {
10049 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10050 "Internal error: xmlSchemaValidateSimpleTypeElement %s content\n",
10051 node->name, NULL);
10052 return (-1);
10053 } else if (ret == 0) {
10054 /* 3.1.2 The element information item must have no element
10055 * information item [children].
10056 */
10057 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_TYPE_3_1_2,
10058 "Element \"%s\" must have no element children.\n",
10059 node->name, NULL);
10060 return (-1);
10061 }
10062 /*
10063 * Validation Rule: Element Locally Valid (Type): 3.1.1
10064 */
10065 attr = node->properties;
10066 while (attr != NULL) {
10067 if ((attr->ns == NULL) ||
10068 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
10069 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
10070 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
10071 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
10072 (!xmlStrEqual
10073 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
10074 xmlSchemaVErr(ctxt, node,
10075 XML_SCHEMAV_CVC_TYPE_3_1_1,
10076 "The attributes of element \"%s\" must be empty, excepting "
10077 "those whose namespace name is identical to "
10078 "http://www.w3.org/2001/XMLSchema-instance and whose local "
10079 "name is one of type, nil, schemaLocation or "
10080 "noNamespaceSchemaLocation.\n",
10081 node->name, attr->name);
10082 return (ctxt->err);
10083 }
10084 attr = attr->next;
10085 }
10086 value = xmlNodeGetContent(child);
10087 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1);
10088 if (value != NULL)
10089 xmlFree(value);
10090
10091 ctxt->type = type;
10092 return (ret);
10093}
Daniel Veillard4255d502002-04-16 15:50:10 +000010094
10095/**
10096 * xmlSchemaValidateElementType:
10097 * @ctxt: a schema validation context
10098 * @node: the top node.
10099 *
10100 * Validate the content of an element type.
10101 * Validation Rule: Element Locally Valid (Complex Type)
10102 *
10103 * Returns 0 if the element is schemas valid, a positive error code
10104 * number otherwise and -1 in case of internal or API error.
10105 */
10106static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010107xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10108{
Daniel Veillard4255d502002-04-16 15:50:10 +000010109 xmlNodePtr child;
10110 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010111 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +000010112 xmlSchemaElementPtr decl;
Daniel Veillard3646d642004-06-02 19:19:14 +000010113 int ret;
10114 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
10115
Daniel Veillard01fa6152004-06-29 17:04:39 +000010116 /* This one is called by xmlSchemaValidateContent only. */
Daniel Veillard3646d642004-06-02 19:19:14 +000010117 /*
10118 * TODO: Look into "xmlSchemaValidateElement" for missing parts, which should
10119 * go in here as well.
10120 */
10121
10122 /* TODO: Is this one called always with an element declaration as the
10123 * context's type?
10124 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010125
10126 oldregexp = ctxt->regexp;
10127
10128 child = ctxt->node;
10129 type = ctxt->type;
10130
10131 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000010132 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10133 "Internal error: xmlSchemaValidateElementType\n",
10134 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010135 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000010136 }
10137 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010138 if (type->minOccurs > 0) {
William M. Bracke7091952004-05-11 15:09:58 +000010139 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
10140 "Element %s: missing child %s\n",
10141 node->name, type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010142 }
10143 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010144 }
10145
10146 /*
10147 * Verify the element matches
10148 */
10149 if (!xmlStrEqual(child->name, type->name)) {
William M. Bracke7091952004-05-11 15:09:58 +000010150 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
10151 "Element %s: missing child %s found %s\n",
10152 node->name, type->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010153 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010154 }
10155 /*
10156 * Verify the attributes
10157 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010158
10159 attrs = ctxt->attr;
10160 attrTop = ctxt->attrTop;
10161
Daniel Veillard01fa6152004-06-29 17:04:39 +000010162 xmlSchemaRegisterAttributes(ctxt, child->properties);
Daniel Veillard3646d642004-06-02 19:19:14 +000010163
Daniel Veillard4255d502002-04-16 15:50:10 +000010164 /*
10165 * Verify the element content recursively
10166 */
10167 decl = (xmlSchemaElementPtr) type;
10168 oldregexp = ctxt->regexp;
10169 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010170 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
10171 (xmlRegExecCallbacks)
10172 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000010173#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010174 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010175#endif
10176 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010177 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
10178 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +000010179
10180 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010181 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010182#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010183 xmlGenericError(xmlGenericErrorContext,
10184 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000010185#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010186 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000010187 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
10188 "Element %s content check failed\n",
10189 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010190 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +000010191 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
10192 "Element %s content check failure\n",
10193 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010194#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010195 } else {
10196 xmlGenericError(xmlGenericErrorContext,
10197 "Element %s content check succeeded\n",
10198 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010199
10200#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010201 }
10202 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000010203 }
10204 /*
10205 * Verify that all attributes were Schemas-validated
10206 */
10207 xmlSchemaCheckAttributes(ctxt, node);
Daniel Veillard3646d642004-06-02 19:19:14 +000010208 if (ctxt->attr != NULL)
10209 xmlSchemaFreeAttributeStates(ctxt->attr);
10210 ctxt->attr = attrs;
10211 ctxt->attrTop = attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000010212 ctxt->regexp = oldregexp;
Daniel Veillard4255d502002-04-16 15:50:10 +000010213 ctxt->node = child;
10214 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010215 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010216}
10217
Daniel Veillard01fa6152004-06-29 17:04:39 +000010218#if 0 /* Not currently used. */
Daniel Veillard4255d502002-04-16 15:50:10 +000010219/**
10220 * xmlSchemaValidateBasicType:
10221 * @ctxt: a schema validation context
10222 * @node: the top node.
10223 *
10224 * Validate the content of an element expected to be a basic type type
10225 *
10226 * Returns 0 if the element is schemas valid, a positive error code
10227 * number otherwise and -1 in case of internal or API error.
10228 */
10229static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010230xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10231{
Daniel Veillard4255d502002-04-16 15:50:10 +000010232 int ret;
10233 xmlNodePtr child, cur;
10234 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010235 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +000010236
10237 child = ctxt->node;
10238 type = ctxt->type;
10239
10240 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000010241 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10242 "Internal error: xmlSchemaValidateBasicType\n",
10243 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010244 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000010245 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010246 if (type->type != XML_SCHEMA_TYPE_BASIC) {
10247 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10248 "Internal error: xmlSchemaValidateBasicType, "
10249 "the given type is not a built-in type.\n",
10250 node->name, NULL);
10251 return (-1);
10252 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010253 /*
10254 * First check the content model of the node.
10255 */
10256 cur = child;
10257 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010258 switch (cur->type) {
10259 case XML_TEXT_NODE:
10260 case XML_CDATA_SECTION_NODE:
10261 case XML_PI_NODE:
10262 case XML_COMMENT_NODE:
10263 case XML_XINCLUDE_START:
10264 case XML_XINCLUDE_END:
10265 break;
10266 case XML_ENTITY_REF_NODE:
10267 case XML_ENTITY_NODE:
10268 TODO break;
10269 case XML_ELEMENT_NODE:
William M. Bracke7091952004-05-11 15:09:58 +000010270 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
10271 "Element %s: child %s should not be present\n",
10272 node->name, cur->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010273 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010274 case XML_ATTRIBUTE_NODE:
10275 case XML_DOCUMENT_NODE:
10276 case XML_DOCUMENT_TYPE_NODE:
10277 case XML_DOCUMENT_FRAG_NODE:
10278 case XML_NOTATION_NODE:
10279 case XML_HTML_DOCUMENT_NODE:
10280 case XML_DTD_NODE:
10281 case XML_ELEMENT_DECL:
10282 case XML_ATTRIBUTE_DECL:
10283 case XML_ENTITY_DECL:
10284 case XML_NAMESPACE_DECL:
10285#ifdef LIBXML_DOCB_ENABLED
10286 case XML_DOCB_DOCUMENT_NODE:
10287#endif
William M. Bracke7091952004-05-11 15:09:58 +000010288 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
10289 "Element %s: node type of node unexpected here\n",
10290 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010291 return (ctxt->err);
10292 }
10293 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010294 }
10295 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010296 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010297 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010298 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +000010299
10300 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010301 xmlSchemaFreeValue(ctxt->value);
10302 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010303 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010304
Daniel Veillard4255d502002-04-16 15:50:10 +000010305 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
Daniel Veillard01fa6152004-06-29 17:04:39 +000010306
Daniel Veillard4255d502002-04-16 15:50:10 +000010307 if (value != NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010308 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +000010309 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +000010310 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
10311 "Element %s: failed to validate basic type %s\n",
10312 node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010313 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010314 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000010315}
Daniel Veillard01fa6152004-06-29 17:04:39 +000010316#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010317
10318/**
10319 * xmlSchemaValidateComplexType:
10320 * @ctxt: a schema validation context
10321 * @node: the top node.
10322 *
10323 * Validate the content of an element expected to be a complex type type
10324 * xmlschema-1.html#cvc-complex-type
10325 * Validation Rule: Element Locally Valid (Complex Type)
10326 *
10327 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000010328 * number otherwise and -1 in case of internal or API error.
10329 * Note on reported errors: Although it might be nice to report
10330 * the name of the simple/complex type, used to validate the content
10331 * of a node, it is quite unnecessary: for global defined types
10332 * the local name of the element is equal to the NCName of the type,
10333 * for local defined types it makes no sense to output the internal
10334 * computed name of the type. TODO: Instead, one should attach the
10335 * struct of the type involved to the error handler - this allows
10336 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000010337 */
10338static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010339xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10340{
Daniel Veillard4255d502002-04-16 15:50:10 +000010341 xmlNodePtr child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010342 xmlSchemaTypePtr type;
10343 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010344
Daniel Veillard4255d502002-04-16 15:50:10 +000010345 child = ctxt->node;
10346 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000010347 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000010348
Daniel Veillard4255d502002-04-16 15:50:10 +000010349 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010350 case XML_SCHEMA_CONTENT_EMPTY: {
10351 /*
10352 * 1 If the {content type} is empty, then the element information
10353 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000010354 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010355 /* TODO: Hmm, Xerces reports nodes like Comment to be invalid
10356 * content, but XSV does not.
10357 */
10358 /*
10359 * TODO: Is the entity stuff correct?
10360 */
10361 while (child != NULL) {
10362 if ((child->type == XML_ELEMENT_NODE) ||
10363 /*
10364 * TODO: Ask Daniel if this are all character nodes.
10365 */
10366 (child->type == XML_TEXT_NODE) ||
10367 (child->type == XML_CDATA_SECTION_NODE) ||
10368 (child->type == XML_ENTITY_REF_NODE) ||
10369 (child->type == XML_ENTITY_NODE)) {
10370 break;
10371 }
10372 child = child->next;
10373 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010374 if (child != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010375 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
10376 "Character or element children are not allowed, "
10377 "because the content type is empty.\n",
10378 NULL, NULL);
10379 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010380 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010381 }
10382 case XML_SCHEMA_CONTENT_ELEMENTS:
10383 case XML_SCHEMA_CONTENT_MIXED:
10384 while (child != NULL) {
10385 if (child->type == XML_ELEMENT_NODE) {
10386 ret = xmlRegExecPushString(ctxt->regexp,
10387 child->name, child);
10388#ifdef DEBUG_AUTOMATA
10389 if (ret < 0)
10390 xmlGenericError(xmlGenericErrorContext,
10391 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000010392 else
10393 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010394 " --> %s\n", child->name);
10395#endif
10396 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
10397 /*
10398 * TODO: Ask Daniel if this are all character nodes.
10399 */
10400 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
10401 (child->type == XML_ENTITY_NODE) ||
10402 (child->type == XML_ENTITY_REF_NODE) ||
10403 (child->type == XML_CDATA_SECTION_NODE))) {
10404 /*
10405 * 2.3 If the {content type} is element-only, then the
10406 * element information item has no character information
10407 * item [children] other than those whose [character
10408 * code] is defined as a white space in [XML 1.0 (Second
10409 * Edition)].
10410 */
10411 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
10412 "Character children are not allowed, "
10413 "because the content type is element-only.\n",
10414 NULL, NULL);
10415 break;
10416 }
10417 child = child->next;
10418 }
10419 break;
10420 case XML_SCHEMA_CONTENT_SIMPLE:
10421 case XML_SCHEMA_CONTENT_BASIC:{
10422 xmlSchemaTypePtr base, anyType;
10423 xmlChar *value = NULL;
10424 /*
10425 * We hit a complexType with a simpleContent resolving
10426 * to a user derived or built-in simple type.
10427 */
10428 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10429 /*
10430 * Internal check for integrity of the base type.
10431 */
10432 base = type->baseType;
10433 while ((base != NULL) &&
10434 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
10435 (base->type != XML_SCHEMA_TYPE_BASIC) &&
10436 (base != anyType)) {
10437 base = base->baseType;
10438 }
10439 if ((base == NULL) ||
10440 (((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) &&
10441 (base->type != XML_SCHEMA_TYPE_SIMPLE)) ||
10442 ((type->contentType == XML_SCHEMA_CONTENT_BASIC) &&
10443 (base->type != XML_SCHEMA_TYPE_BASIC)))) {
10444 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10445 "Internal error: xmlSchemaValidateComplexType, "
10446 "Element \"%s\": the base type of the corresponding "
10447 "complex type \"%s\" is not a user derived or a "
10448 "built-in simple type.\n",
10449 node->name, type->name);
10450 return (-1);
10451 }
10452 /*
10453 * 2.2 If the {content type} is a simple type definition,
10454 * then the element information item has no element
10455 * information item [children], and the ·normalized value·
10456 * of the element information item is ·valid· with respect
10457 * to that simple type definition as defined by String
10458 * Valid (§3.14.4).
10459 */
10460 child = node->children;
10461 while (child != NULL) {
10462 if (child->type == XML_ELEMENT_NODE) {
10463 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
10464 "Element children are not allowed, because "
10465 "the content type is a simple type.\n",
10466 NULL, NULL);
10467 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
10468 break;
10469 }
10470 child = child->next;
10471 }
10472 if (ret == 0) {
10473 /*
10474 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000010475 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010476 if (ctxt->node == NULL)
10477 value = NULL;
10478 else
10479 value = xmlNodeGetContent(node);
10480 ctxt->type = base;
10481 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1);
10482 ctxt->type = type;
10483 if (ret > 0) {
10484 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
10485 "The character value "
10486 "is not valid with respect to the simple type.\n",
10487 NULL, NULL);
10488 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
10489 } else if (ret < 0) {
10490 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10491 "Internal error: xmlSchemaValidateComplexType, "
10492 "Element \"%s\": error while validating character "
10493 "content against complex type \"%s\".\n",
10494 node->name, type->name);
10495 return (-1);
10496 }
10497 }
10498 if (ret == 0) {
10499 /*
10500 * Apply facets of the complexType. Be sure to pass the
10501 * built-in type to xmlSchemaValidateFacetsInternal.
10502 */
10503 /* TODO: I don't know yet if the facets of the simple type
10504 * are used, or if the facets, defined by this complex type,
10505 * are to be used only. This here applies both facet sets.
10506 */
10507 while (base->type != XML_SCHEMA_TYPE_BASIC)
10508 base = base->baseType;
10509 if (base == NULL) {
10510 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10511 "Internal error: xmlSchemaValidateComplexType, "
10512 "Element \"%s\": error while validating character "
10513 "content against complex type \"%s\"; failed to "
10514 "compute the built-in simple type for facet "
10515 "validation.\n",
10516 node->name, type->name);
10517 return (-1);
10518 }
10519 ret = xmlSchemaValidateFacetsInternal(ctxt, base,
10520 type->facetSet, value, 1);
10521 if (ret > 0) {
10522 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
10523 "The character value "
10524 "is not valid with respect to the simple type.\n",
10525 NULL, NULL);
10526 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
10527 } else if (ret < 0) {
10528 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10529 "Internal error: xmlSchemaValidateComplexType, "
10530 "Element \"%s\": error while validating character "
10531 "content against complex type \"%s\"; failed to "
10532 "apply facets.\n",
10533 type->name, NULL);
10534 }
10535 }
10536 if (value != NULL)
10537 xmlFree(value);
10538 /* TODO: facets */
10539 break;
10540 }
10541 /*
10542 case XML_SCHEMA_CONTENT_SIMPLE:{
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010543 if (type->subtypes != NULL) {
10544 ctxt->type = type->subtypes;
10545 xmlSchemaValidateComplexType(ctxt, node);
10546 }
10547 if (type->baseType != NULL) {
10548 ctxt->type = type->baseType;
10549 xmlSchemaValidateComplexType(ctxt, node);
10550 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010551 * Removed due to changes of attribute validation:
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010552 if (type->attributes != NULL) {
10553 xmlSchemaValidateAttributes(ctxt, node,
10554 type->attributes);
10555 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010556 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010557 ctxt->type = type;
10558 break;
10559 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010560 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010561 default:
10562 TODO xmlGenericError(xmlGenericErrorContext,
10563 "unimplemented content type %d\n",
10564 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000010565 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010566 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010567 xmlSchemaValidateAttributes(ctxt, node, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010568 }
10569 ctxt->cur = node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010570 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010571}
10572
10573/**
10574 * xmlSchemaValidateContent:
10575 * @ctxt: a schema validation context
10576 * @elem: an element
10577 * @type: the type declaration
10578 *
10579 * Validate the content of an element against the type.
10580 *
10581 * Returns 0 if the element is schemas valid, a positive error code
10582 * number otherwise and -1 in case of internal or API error.
10583 */
10584static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010585xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10586{
Daniel Veillard4255d502002-04-16 15:50:10 +000010587 xmlNodePtr child;
10588 xmlSchemaTypePtr type;
10589
10590 child = ctxt->node;
10591 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000010592 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000010593
Daniel Veillard82bbbd42003-05-11 20:16:09 +000010594 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +000010595
Daniel Veillard4255d502002-04-16 15:50:10 +000010596 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010597 case XML_SCHEMA_TYPE_ANY:
10598 /* Any type will do it, fine */
10599 TODO /* handle recursivity */
10600 break;
10601 case XML_SCHEMA_TYPE_COMPLEX:
10602 xmlSchemaValidateComplexType(ctxt, node);
10603 break;
10604 case XML_SCHEMA_TYPE_ELEMENT:{
10605 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
10606
10607 /*
10608 * Handle element reference here
10609 */
10610 if (decl->ref != NULL) {
10611 if (decl->refDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000010612 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10613 "Internal error: element reference %s "
10614 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010615 return (-1);
10616 }
10617 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
10618 decl = decl->refDecl;
10619 }
William M. Bracke7091952004-05-11 15:09:58 +000010620 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010621 xmlSchemaValidateElementType(ctxt, node);
10622 ctxt->type = type;
10623 break;
10624 }
10625 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010626 case XML_SCHEMA_TYPE_SIMPLE:
10627 xmlSchemaValidateSimpleTypeElement(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010628 break;
10629 case XML_SCHEMA_TYPE_FACET:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010630 TODO break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010631 case XML_SCHEMA_TYPE_SEQUENCE:
10632 TODO break;
10633 case XML_SCHEMA_TYPE_CHOICE:
10634 TODO break;
10635 case XML_SCHEMA_TYPE_ALL:
10636 TODO break;
10637 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10638 TODO break;
10639 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10640 TODO break;
10641 case XML_SCHEMA_TYPE_UR:
10642 TODO break;
10643 case XML_SCHEMA_TYPE_RESTRICTION:
10644 /*xmlSchemaValidateRestrictionType(ctxt, node); */
10645 TODO break;
10646 case XML_SCHEMA_TYPE_EXTENSION:
10647 TODO break;
10648 case XML_SCHEMA_TYPE_ATTRIBUTE:
10649 TODO break;
10650 case XML_SCHEMA_TYPE_GROUP:
10651 TODO break;
10652 case XML_SCHEMA_TYPE_NOTATION:
10653 TODO break;
10654 case XML_SCHEMA_TYPE_LIST:
10655 TODO break;
10656 case XML_SCHEMA_TYPE_UNION:
10657 TODO break;
10658 case XML_SCHEMA_FACET_MININCLUSIVE:
10659 TODO break;
10660 case XML_SCHEMA_FACET_MINEXCLUSIVE:
10661 TODO break;
10662 case XML_SCHEMA_FACET_MAXINCLUSIVE:
10663 TODO break;
10664 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
10665 TODO break;
10666 case XML_SCHEMA_FACET_TOTALDIGITS:
10667 TODO break;
10668 case XML_SCHEMA_FACET_FRACTIONDIGITS:
10669 TODO break;
10670 case XML_SCHEMA_FACET_PATTERN:
10671 TODO break;
10672 case XML_SCHEMA_FACET_ENUMERATION:
10673 TODO break;
10674 case XML_SCHEMA_FACET_WHITESPACE:
10675 TODO break;
10676 case XML_SCHEMA_FACET_LENGTH:
10677 TODO break;
10678 case XML_SCHEMA_FACET_MAXLENGTH:
10679 TODO break;
10680 case XML_SCHEMA_FACET_MINLENGTH:
10681 TODO break;
10682 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
10683 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +000010684 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
10685 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +000010686 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010687
10688 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010689 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010690 ctxt->node = ctxt->node->next;
10691 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010692 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010693}
10694
10695/**
10696 * xmlSchemaValidateType:
10697 * @ctxt: a schema validation context
10698 * @elem: an element
10699 * @type: the list of type declarations
10700 *
10701 * Validate the content of an element against the types.
10702 *
10703 * Returns 0 if the element is schemas valid, a positive error code
10704 * number otherwise and -1 in case of internal or API error.
10705 */
10706static int
10707xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010708 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
10709{
Daniel Veillard4255d502002-04-16 15:50:10 +000010710 xmlChar *nil;
10711
Daniel Veillard2db8c122003-07-08 12:16:59 +000010712 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010713 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +000010714
Daniel Veillard3646d642004-06-02 19:19:14 +000010715 /* This one is called by "xmlSchemaValidateElementType" and
10716 * "xmlSchemaValidateElement".
10717 */
10718
Daniel Veillard4255d502002-04-16 15:50:10 +000010719 /*
10720 * 3.3.4 : 2
10721 */
10722 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
William M. Bracke7091952004-05-11 15:09:58 +000010723 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
10724 "Element declaration %s is abstract\n",
10725 elemDecl->name, NULL);
10726 /* Changed, since the element declaration is abstract and not
10727 * the element itself. */
10728 /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
10729 "Element %s is abstract\n", elem->name, NULL); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010730 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010731 }
10732 /*
10733 * 3.3.4: 3
10734 */
10735 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
10736 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010737 /* 3.3.4: 3.2 */
10738 if (xmlStrEqual(nil, BAD_CAST "true")) {
10739 if (elem->children != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000010740 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
10741 "Element %s is not empty\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010742 return (ctxt->err);
10743 }
10744 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
10745 (elemDecl->value != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000010746 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
10747 "Empty element %s cannot get a fixed value\n",
10748 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010749 return (ctxt->err);
10750 }
10751 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010752 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010753 /* 3.3.4: 3.1 */
10754 if (nil != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000010755 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
10756 "Element %s with xs:nil but not nillable\n",
10757 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010758 xmlFree(nil);
10759 return (ctxt->err);
10760 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010761 }
10762
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010763 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +000010764
10765 ctxt->type = elemDecl->subtypes;
10766 ctxt->node = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010767 xmlSchemaValidateContent(ctxt, elem);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010768 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010769}
10770
10771
10772/**
10773 * xmlSchemaValidateAttributes:
10774 * @ctxt: a schema validation context
10775 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000010776 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000010777 *
10778 * Validate the attributes of an element.
10779 *
10780 * Returns 0 if the element is schemas valid, a positive error code
10781 * number otherwise and -1 in case of internal or API error.
10782 */
10783static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010784xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010785{
Daniel Veillard3646d642004-06-02 19:19:14 +000010786 int ret;
10787 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +000010788 xmlChar *value;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000010789 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000010790 xmlSchemaAttributeLinkPtr attrUse;
10791 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000010792 int found;
William M. Brack803812b2004-06-03 02:11:24 +000010793 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000010794#ifdef DEBUG_ATTR_VALIDATION
10795 int redundant = 0;
10796#endif
10797 if (type->type != XML_SCHEMA_TYPE_COMPLEX) {
10798 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INTERNAL,
10799 "Internal error: xmlSchemaValidateAttributes: "
10800 "given type \"%s\"is not a complexType\n",
10801 type->name, NULL);
10802 return(-1);
10803 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010804
Daniel Veillard3646d642004-06-02 19:19:14 +000010805 if ((type->attributeUses == NULL) && (type->attributeWildcard == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010806 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010807
10808 attrUse = type->attributeUses;
10809
10810 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000010811 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010812 attrDecl = attrUse->attr;
10813#ifdef DEBUG_ATTR_VALIDATION
10814 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
10815 printf("attr use - use: %d\n", attrDecl->occurs);
10816#endif
10817 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
10818
10819 if (curState->decl == attrUse->attr) {
10820#ifdef DEBUG_ATTR_VALIDATION
10821 redundant = 1;
10822#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010823 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010824 attr = curState->attr;
10825#ifdef DEBUG_ATTR_VALIDATION
10826 printf("attr - name: %s\n", attr->name);
10827 if (attr->ns != NULL)
10828 printf("attr - ns: %s\n", attr->ns->href);
10829 else
10830 printf("attr - ns: none\n");
10831#endif
10832 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010833 if (attr == NULL)
10834 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000010835 if (attrDecl->ref != NULL) {
10836 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010837 continue;
10838 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010839 if ((attrDecl->refNs == NULL) ||
10840 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010841 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000010842 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010843 continue;
10844 }
10845 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000010846 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010847 continue;
10848 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010849 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010850 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010851 if (attr->ns == NULL) {
10852 /*
William M. Bracke7091952004-05-11 15:09:58 +000010853 * accept an unqualified attribute only if the target
10854 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010855 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010856 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000010857 /*
10858 * This check was removed, since the target namespace
10859 * was evaluated during parsing and already took
10860 * "attributeFormDefault" into account.
10861 */
10862 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010863 continue;
10864 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000010865 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010866 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000010867 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010868 attr->ns->href))
10869 continue;
10870 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010871 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010872#ifdef DEBUG_ATTR_VALIDATION
10873 printf("found\n");
10874#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000010875 found = 1;
Daniel Veillard50355f02004-06-08 17:52:16 +000010876 ctxt->cur = (xmlNodePtr) attr;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010877 ctxt->node = attr->children;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000010878
Daniel Veillard3646d642004-06-02 19:19:14 +000010879 if (attrDecl->subtypes == NULL) {
10880 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
10881 curState->decl = attrDecl;
10882 /*
10883 * This could be put into "xmlSchemaCheckAttributes" as well, but
10884 * since it reports an internal error, it better stays here to ease
10885 * debugging.
10886 */
William M. Bracke7091952004-05-11 15:09:58 +000010887 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
10888 "Internal error: attribute %s type not resolved\n",
10889 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010890 continue;
10891 }
10892 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010893 ctxt->type = attrDecl->subtypes;
10894 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1);
10895 ctxt->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +000010896 if (ret != 0)
10897 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
10898 else
10899 curState->state = XML_SCHEMAS_ATTR_CHECKED;
10900 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010901 if (value != NULL) {
10902 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +000010903 }
10904 }
10905 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10906 xmlSchemaAttrStatePtr tmp;
10907
10908#ifdef DEBUG_ATTR_VALIDATION
10909 printf("required attr not found\n");
10910#endif
10911 /*
10912 * Add a new dummy attribute state.
10913 */
10914 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
10915 if (tmp == NULL) {
10916 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
10917 return (-1);
10918 }
10919 tmp->attr = NULL;
10920 tmp->state = XML_SCHEMAS_ATTR_MISSING;
10921 tmp->decl = attrDecl;
10922 tmp->next = NULL;
10923
10924 if (reqAttrStates == NULL) {
10925 reqAttrStates = tmp;
10926 reqAttrStatesTop = tmp;
10927 } else {
10928 reqAttrStatesTop->next = tmp;
10929 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010930 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010931
10932 }
10933 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010934 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010935 /*
10936 * Add required attributes to the attribute states of the context.
10937 */
10938 if (reqAttrStates != NULL) {
10939 if (ctxt->attr == NULL) {
10940 ctxt->attr = reqAttrStates;
10941 } else {
10942 ctxt->attrTop->next = reqAttrStates;
10943 }
10944 ctxt->attrTop = reqAttrStatesTop;
10945 }
10946 /*
10947 * Process wildcards.
10948 */
10949 if (type->attributeWildcard != NULL) {
10950#ifdef DEBUG_ATTR_VALIDATION
10951 xmlSchemaWildcardNsPtr ns;
10952 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000010953 if (type->attributeWildcard->processContents ==
10954 XML_SCHEMAS_ANY_LAX)
10955 printf("processContents: lax\n");
10956 else if (type->attributeWildcard->processContents ==
10957 XML_SCHEMAS_ANY_STRICT)
10958 printf("processContents: strict\n");
10959 else
10960 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000010961 if (type->attributeWildcard->any)
10962 printf("type: any\n");
10963 else if (type->attributeWildcard->negNsSet != NULL) {
10964 printf("type: negated\n");
10965 if (type->attributeWildcard->negNsSet->value == NULL)
10966 printf("ns: (absent)\n");
10967 else
10968 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
10969 } else if (type->attributeWildcard->nsSet != NULL) {
10970 printf("type: set\n");
10971 ns = type->attributeWildcard->nsSet;
10972 while (ns != NULL) {
10973 if (ns->value == NULL)
10974 printf("ns: (absent)\n");
10975 else
10976 printf("ns: %s\n", ns->value);
10977 ns = ns->next;
10978 }
10979 } else
10980 printf("empty\n");
10981
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000010982
10983#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000010984 curState = ctxt->attr;
10985 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000010986 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
10987 if (curState->attr->ns != NULL)
10988 nsURI = curState->attr->ns->href;
10989 else
10990 nsURI = NULL;
10991 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
10992 nsURI)) {
10993 /*
10994 * Handle processContents.
10995 */
10996 if ((type->attributeWildcard->processContents ==
10997 XML_SCHEMAS_ANY_LAX) ||
10998 (type->attributeWildcard->processContents ==
10999 XML_SCHEMAS_ANY_STRICT)) {
11000
11001 attr = curState->attr;
11002 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
11003 attr->name, nsURI);
11004 if (attrDecl != NULL) {
11005 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011006 ctxt->type = attrDecl->subtypes;
11007 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1);
11008 ctxt->type = type;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000011009 if (ret != 0)
11010 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
11011 else
11012 curState->state = XML_SCHEMAS_ATTR_CHECKED;
11013 curState->decl = attrDecl;
11014 if (value != NULL) {
11015 xmlFree(value);
11016 }
11017
11018 } else if (type->attributeWildcard->processContents ==
11019 XML_SCHEMAS_ANY_LAX) {
11020 curState->state = XML_SCHEMAS_ATTR_CHECKED;
11021 }
11022 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000011023 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000011024 }
11025 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011026 curState = curState->next;
11027 }
11028 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011029#ifdef DEBUG_ATTR_VALIDATION
11030 if (redundant)
11031 xmlGenericError(xmlGenericErrorContext,
11032 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
11033 type->name);
11034#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011035 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011036}
11037
11038/**
11039 * xmlSchemaValidateElement:
11040 * @ctxt: a schema validation context
11041 * @elem: an element
11042 *
11043 * Validate an element in a tree
11044 *
11045 * Returns 0 if the element is schemas valid, a positive error code
11046 * number otherwise and -1 in case of internal or API error.
11047 */
11048static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011049xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
11050{
Daniel Veillard4255d502002-04-16 15:50:10 +000011051 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +000011052 int ret;
11053 xmlSchemaAttrStatePtr attrs, attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000011054
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011055 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011056 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11057 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011058 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011059 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11060 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011061 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011062 /* This one is called by xmlSchemaValidateDocument only. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011063
Daniel Veillard4255d502002-04-16 15:50:10 +000011064 /*
11065 * 3.3.4 : 1
11066 */
11067 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000011068 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
11069 "Element %s not declared\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011070 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011071 }
11072 if (elemDecl->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000011073 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
11074 "Element %s has no type\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011075 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011076 }
11077 /*
11078 * Verify the attributes
11079 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011080 attrs = ctxt->attr;
11081 attrTop = ctxt->attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000011082 xmlSchemaRegisterAttributes(ctxt, elem->properties);
Daniel Veillard4255d502002-04-16 15:50:10 +000011083 /*
11084 * Verify the element content recursively
11085 */
11086 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011087 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
11088 (xmlRegExecCallbacks)
11089 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011090#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011091 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011092#endif
11093 }
11094 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011095 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011096 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011097#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011098 xmlGenericError(xmlGenericErrorContext,
11099 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011100#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011101 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000011102 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
11103 "Element %s content check failed\n",
11104 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011105 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +000011106 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
11107 "Element %s content check failed\n",
11108 elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011109#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011110 } else {
11111 xmlGenericError(xmlGenericErrorContext,
11112 "Element %s content check succeeded\n",
11113 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011114
11115#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011116 }
11117 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000011118 }
11119 /*
11120 * Verify that all attributes were Schemas-validated
11121 */
11122 xmlSchemaCheckAttributes(ctxt, elem);
Daniel Veillard3646d642004-06-02 19:19:14 +000011123 if (ctxt->attr != NULL)
11124 xmlSchemaFreeAttributeStates(ctxt->attr);
11125 ctxt->attr = attrs;
11126 ctxt->attrTop = attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011127
11128 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011129}
11130
11131/**
11132 * xmlSchemaValidateDocument:
11133 * @ctxt: a schema validation context
11134 * @doc: a parsed document tree
11135 *
11136 * Validate a document tree in memory.
11137 *
11138 * Returns 0 if the document is schemas valid, a positive error code
11139 * number otherwise and -1 in case of internal or API error.
11140 */
11141static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011142xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
11143{
Daniel Veillard4255d502002-04-16 15:50:10 +000011144 xmlNodePtr root;
11145 xmlSchemaElementPtr elemDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011146
Daniel Veillard4255d502002-04-16 15:50:10 +000011147 root = xmlDocGetRootElement(doc);
11148 if (root == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000011149 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
11150 "document has no root\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011151 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011152 }
William M. Bracke7091952004-05-11 15:09:58 +000011153
Daniel Veillard4255d502002-04-16 15:50:10 +000011154 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011155 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11156 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011157 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011158 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11159 root->name, NULL, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011160
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011161 /*
11162 * special case whe elementFormDefault is unqualified for top-level elem.
11163 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011164 /* Removed, since elementFormDefault does not apply to top level
11165 * elements */
11166 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011167 if ((elemDecl == NULL) && (root->ns != NULL) &&
11168 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
11169 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
11170 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11171 root->name, NULL, NULL);
11172 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011173 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011174
Daniel Veillard4255d502002-04-16 15:50:10 +000011175 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000011176 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
11177 "Element %s not declared\n", root->name, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011178 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000011179 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
Daniel Veillard3646d642004-06-02 19:19:14 +000011180 "Root element %s not global\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011181 }
11182 /*
11183 * Okay, start the recursive validation
11184 */
11185 xmlSchemaValidateElement(ctxt, root);
11186
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011187 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011188}
11189
11190/************************************************************************
11191 * *
11192 * SAX Validation code *
11193 * *
11194 ************************************************************************/
11195
11196/************************************************************************
11197 * *
11198 * Validation interfaces *
11199 * *
11200 ************************************************************************/
11201
11202/**
11203 * xmlSchemaNewValidCtxt:
11204 * @schema: a precompiled XML Schemas
11205 *
11206 * Create an XML Schemas validation context based on the given schema
11207 *
11208 * Returns the validation context or NULL in case of error
11209 */
11210xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011211xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
11212{
Daniel Veillard4255d502002-04-16 15:50:10 +000011213 xmlSchemaValidCtxtPtr ret;
11214
11215 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
11216 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011217 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011218 return (NULL);
11219 }
11220 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
11221 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000011222 /*
11223 * Removed due to changes of the attribute state list.
William M. Brack803812b2004-06-03 02:11:24 +000011224 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011225 /* ret->attrNr = 0; */
11226 /* ret->attrMax = 10; */
11227 /* ret->attrBase = NULL; */
11228 ret->attrTop = NULL;
11229 ret->attr = NULL;
11230 /*
11231 * Removed due to changes of the attribute state list.
William M. Brack803812b2004-06-03 02:11:24 +000011232 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011233 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011234 sizeof
11235 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +000011236 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011237 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
11238 free(ret);
11239 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011240 }
11241 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
Daniel Veillard3646d642004-06-02 19:19:14 +000011242 */
11243
Daniel Veillard4255d502002-04-16 15:50:10 +000011244 return (ret);
11245}
11246
11247/**
11248 * xmlSchemaFreeValidCtxt:
11249 * @ctxt: the schema validation context
11250 *
11251 * Free the resources associated to the schema validation context
11252 */
11253void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011254xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
11255{
Daniel Veillard4255d502002-04-16 15:50:10 +000011256 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011257 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011258 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011259 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000011260 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011261 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +000011262 xmlFree(ctxt);
11263}
11264
11265/**
11266 * xmlSchemaSetValidErrors:
11267 * @ctxt: a schema validation context
11268 * @err: the error function
11269 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000011270 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000011271 *
11272 * Set the error and warning callback informations
11273 */
11274void
11275xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011276 xmlSchemaValidityErrorFunc err,
11277 xmlSchemaValidityWarningFunc warn, void *ctx)
11278{
Daniel Veillard4255d502002-04-16 15:50:10 +000011279 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011280 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011281 ctxt->error = err;
11282 ctxt->warning = warn;
11283 ctxt->userData = ctx;
11284}
11285
11286/**
11287 * xmlSchemaValidateDoc:
11288 * @ctxt: a schema validation context
11289 * @doc: a parsed document tree
11290 *
11291 * Validate a document tree in memory.
11292 *
11293 * Returns 0 if the document is schemas valid, a positive error code
11294 * number otherwise and -1 in case of internal or API error.
11295 */
11296int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011297xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
11298{
Daniel Veillard4255d502002-04-16 15:50:10 +000011299 int ret;
11300
11301 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011302 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011303
11304 ctxt->doc = doc;
11305 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011306 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000011307}
11308
11309/**
11310 * xmlSchemaValidateStream:
11311 * @ctxt: a schema validation context
11312 * @input: the input to use for reading the data
11313 * @enc: an optional encoding information
11314 * @sax: a SAX handler for the resulting events
11315 * @user_data: the context to provide to the SAX handler.
11316 *
11317 * Validate a document tree in memory.
11318 *
11319 * Returns 0 if the document is schemas valid, a positive error code
11320 * number otherwise and -1 in case of internal or API error.
11321 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011322int
Daniel Veillard4255d502002-04-16 15:50:10 +000011323xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011324 xmlParserInputBufferPtr input, xmlCharEncoding enc,
11325 xmlSAXHandlerPtr sax, void *user_data)
11326{
Daniel Veillard4255d502002-04-16 15:50:10 +000011327 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011328 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011329 ctxt->input = input;
11330 ctxt->enc = enc;
11331 ctxt->sax = sax;
11332 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011333 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011334}
11335
11336#endif /* LIBXML_SCHEMAS_ENABLED */